Copepod Collection
Copepods were collected at approximately weekly intervals from Lake
Champlain (Burlington Fishing Pier). Plankton was collected from the top
3 meters using a 250 um mesh net.
# # Lake Champlain near Burlington, VT
# siteNumber = "04294500"
# ChamplainInfo = readNWISsite(siteNumber)
# parameterCd = "00010"
# startDate = "2023-01-01"
# endDate = "2024-5-20"
# #statCd = c("00001", "00002","00003", "00011") # 1 - max, 2 - min, 3 = mean
#
# # Constructs the URL for the data wanted then downloads the data
# url = constructNWISURL(siteNumbers = siteNumber, parameterCd = parameterCd,
# startDate = startDate, endDate = endDate, service = "uv")
#
# raw_temps = importWaterML1(url, asDateTime = T) %>%
# mutate("date" = as.Date(dateTime),
# "hour" = hour(dateTime)) %>%
# select(dateTime, tz_cd, date, hour, degC = X_00010_00000)
#
# temp_data = raw_temps %>%
# select(date, hour, "temp" = degC)
#
# write.csv(temp_data, file = "./Output/Data/champlain_temps.csv", row.names = F)
Collections began in late May 2023. Several gaps are present, but
collections have continued at roughly weekly intervals since then.
Copepods from 48 collections were used to make a total of 1312 thermal
limit measurements. Over this time period, collection temperatures
ranged from 2.5 to 26.5°C.
There is substantial variation in thermal limits across the species
collected. There is also some degree of variation within the species,
with thermal limits increasing slightly during the summer.
## Daily values for the period examined by dataset
collection_conditions = temp_data %>%
ungroup() %>%
group_by(date) %>%
summarise(mean_temp = mean(temp),
med_temp = median(temp),
var_temp = var(temp),
min_temp = min(temp),
max_temp = max(temp)) %>%
mutate("range_temp" = max_temp - min_temp,
date = as.Date(date)) %>%
ungroup() %>%
filter(date >= (min(as.Date(full_data$collection_date)) - 7)) %>%
left_join(unique(select(full_data, collection_date, collection_temp)), by = join_by(date == collection_date))
## Mean female thermal limits for each species, grouped by collection
species_summaries = full_data %>%
#filter(sex == "female") %>%
group_by(sp_name, collection_date, collection_temp) %>%
summarise("mean_ctmax" = mean(ctmax),
"sample_size" = n(),
"ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
"ctmax_var" = var(ctmax),
"mean_size" = mean(size),
"size_st_err" = (sd(size) / sqrt(sample_size)),
"size_var" = var(size)) %>%
ungroup() %>%
complete(sp_name, collection_date) %>%
arrange(desc(sample_size))
adult_summaries = full_data %>%
filter(sex == "female") %>%
group_by(sp_name, collection_date, collection_temp) %>%
summarise("mean_ctmax" = mean(ctmax),
"sample_size" = n(),
"ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
"ctmax_var" = var(ctmax),
"mean_size" = mean(size),
"size_st_err" = (sd(size) / sqrt(sample_size)),
"size_var" = var(size)) %>%
ungroup() %>%
complete(sp_name, collection_date) %>%
arrange(desc(sample_size))
tseries_data = full_data %>%
mutate(sp_name = fct_reorder(sp_name, ctmax, .desc = T))
ggplot() +
geom_vline(data = unique(select(tseries_data, collection_date)),
aes(xintercept = as.Date(collection_date)),
colour = "grey90",
linewidth = 1) +
geom_line(data = collection_conditions,
aes(x = as.Date(date), y = mean_temp),
colour = "black",
linewidth = 2) +
# geom_errorbar(data = species_summaries,
# aes(x = as.Date(collection_date),
# ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
# colour = sp_name),
# position = position_dodge(width = 1),
# width = 5, linewidth = 1) +
# geom_point(data = adult_summaries,
# aes(x = as.Date(collection_date), y = mean_ctmax, colour = sp_name, size = sample_size)) +
geom_point(data = tseries_data,
aes(x = as.Date(collection_date), y = ctmax, colour = sp_name),
size = 2, position = position_jitter(width = 1, height = 0)) +
scale_colour_manual(values = species_cols) +
labs(x = "Date",
y = "Temperature (°C)",
colour = "Species",
size = "Sample Size") +
theme_matt() +
theme(legend.position = "right")

lake_temps = ggplot() +
geom_line(data = collection_conditions,
aes(x = as.Date(date), y = mean_temp),
colour = "black",
linewidth = 1) +
labs(x = "Date",
y = "Temperature (°C)",
colour = "Species",
size = "Sample Size") +
theme_matt() +
theme(legend.position = "right")
Temperatures observed at the time of collection closely resembled the
maximum daily temperature from the temperature sensor data. Maximum
temperature was used as a proxy instead of mean temperature as
collections were usually made during afternoons or early evenings, just
following the warmest part of the day.
collection_conditions %>%
drop_na(collection_temp) %>%
ggplot(aes(x = max_temp, y = collection_temp)) +
geom_abline(intercept = 0, slope = 1,
linewidth = 1, colour = "grey") +
geom_point(size = 3) +
scale_x_continuous(breaks = c(5,15,25)) +
scale_y_continuous(breaks = c(5,15,25)) +
labs(x = "Max. Temp. from Sensor (°C)",
y = "Collection Temp. (°C)") +
theme_matt()

Size also varied, but primarily between rather than within
species.
ggplot() +
geom_vline(data = unique(select(full_data, collection_date)),
aes(xintercept = as.Date(collection_date)),
colour = "grey90",
linewidth = 1) +
geom_line(data = collection_conditions,
aes(x = as.Date(date), y = mean_temp),
colour = "black",
linewidth = 2) +
# geom_errorbar(data = species_summaries,
# aes(x = as.Date(collection_date),
# ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
# colour = sp_name),
# position = position_dodge(width = 1),
# width = 5, linewidth = 1) +
geom_point(data = adult_summaries,
aes(x = as.Date(collection_date), y = mean_size * 40, colour = sp_name, size = sample_size),
position = position_dodge(width = 1)) +
scale_colour_manual(values = species_cols) +
scale_y_continuous(
name = "Temperature", # Features of the first axis
sec.axis = sec_axis(~./40, name="Prosome Length (mm)"), # Add a second axis and specify its features
breaks = c(0,5,10,15,20,25,30)
) +
labs(x = "Date",
y = "Temperature (°C)",
colour = "Species") +
theme_matt() +
theme(legend.position = "right")

sample_dates_plot = full_data %>%
filter(sp_name != "Osphranticum labronectum") %>%
mutate(sp_name = as.factor(sp_name),
sp_name = fct_reorder(sp_name, ctmax)) %>%
ggplot(aes(x = lubridate::as_date(collection_date),
y = sp_name, fill = sp_name)) +
# geom_vline(xintercept = as_date(
# c("2023-05-01",
# "2023-09-01",
# "2024-01-01",
# "2024-05-01")),
# colour = "grey",
# linewidth = 1) +
geom_density_ridges(bandwidth = 30,
jittered_points = TRUE,
point_shape = 21,
point_size = 1,
point_colour = "grey30",
point_alpha = 0.8,
alpha = 0.8,
position = position_points_jitter(
height = 0.1, width = 0)) +
scale_fill_manual(values = species_cols) +
scale_x_date(date_breaks = "3 months",
date_labels = "%b") +
coord_cartesian(xlim = lubridate::as_date(c("2023-06-08", "2024-05-08"))) +
labs(x = "Day of Year",
y = "Species") +
theme_matt() +
#theme_ridges(grid = T) +
theme(legend.position = "none",
axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
The samples captured the broad seasonal changes in calanoid copepod
community composition in the lake. We note, however, that rare species
(e.g. Senecella and Limnocalanus) were often
preferentially sampled, so are over-represented in the data set.
Throughout the season, the prevalence of various unidentified
pathogens also varied, with very little infection observed during the
Winter and Spring.
pathogen_cols = c("no" = "grey95", "cloudy" = "honeydew3", "spot" = "antiquewhite3", "other" = "tomato3")
full_data %>%
select(collection_date, dev_eggs, pathogen, lipids, sp_name, sex) %>%
group_by() %>%
filter(sex != "juvenile") %>%
group_by(collection_date) %>%
count(pathogen) %>%
filter(pathogen != "uncertain") %>%
pivot_wider(id_cols = "collection_date",
names_from = pathogen,
values_from = n,
values_fill = 0) %>%
mutate(total = sum(no, cloudy, spot, other)) %>%
pivot_longer(cols = c(no, cloudy, spot, other),
names_to = "pathogen",
values_to = "count") %>%
mutate(percent = count/total,
collection_date = lubridate::as_date(collection_date),
pathogen = fct_relevel(pathogen, "no", "cloudy", "spot", "other")) %>%
ggplot(aes(x = collection_date, y = percent, fill = pathogen)) +
geom_area() +
scale_fill_manual(values = pathogen_cols) +
scale_y_continuous(breaks = c(0,1)) +
labs(x = "Collection Date",
y = "Proportion",
fill = "Pathogen") +
theme_minimal(base_size = 20) +
theme(panel.grid = element_blank(),
axis.ticks = element_line())

The transparent bodies of these copepods also allowed us to examine
seasonal patterns in lipid reserves and in the production of eggs.
Maturing oocytes are visible in female copepods before they are
released. There was no strong seasonal cycle in the production of these
eggs in any species, and instead, females were reproductively active
throughout their respective seasons of occurence.
dev_eggs_cols = c("no" = "grey95", "yes" = "lightblue3")
full_data %>%
select(collection_date, dev_eggs, pathogen, lipids, sp_name, sex) %>%
group_by(sp_name) %>%
filter(sex != "juvenile") %>%
group_by(sp_name, collection_date) %>%
count(dev_eggs) %>%
filter(dev_eggs != "uncertain") %>%
pivot_wider(id_cols = c("collection_date", "sp_name"),
names_from = dev_eggs,
values_from = n,
values_fill = 0) %>%
mutate(total = sum(no, yes)) %>%
pivot_longer(cols = c(no, yes),
names_to = "dev_eggs",
values_to = "count") %>%
mutate(percent = count/total,
collection_date = lubridate::as_date(collection_date),
dev_eggs = fct_relevel(dev_eggs, "no", "yes")) %>%
ungroup() %>%
complete(collection_date, nesting(sp_name, dev_eggs), fill = list(percent = 1)) %>%
mutate(percent = if_else(is.na(total) & dev_eggs == "yes", 0, percent)) %>%
ggplot(aes(x = collection_date, y = percent, fill = dev_eggs)) +
facet_wrap(sp_name~., ncol = 1) +
geom_area() +
scale_fill_manual(values = dev_eggs_cols) +
scale_y_continuous(breaks = c(0,1)) +
labs(x = "Collection Date",
y = "Proportion",
fill = "Developing \nEggs") +
theme_minimal(base_size = 20) +
theme(panel.grid = element_blank(),
axis.ticks = element_line())

The presence of lipids varied across species, with only L.
minutus, L. sicilis, and Limnocalanus regularly
possessing lipid stores.
lipid_cols = c("no" = "grey95", "yes" = "sienna2")
full_data %>%
select(collection_date, dev_eggs, pathogen, lipids, sp_name, sex) %>%
group_by(sp_name) %>%
filter(sex != "juvenile") %>%
group_by(sp_name, collection_date) %>%
count(lipids) %>%
filter(lipids != "uncertain") %>%
pivot_wider(id_cols = c("collection_date", "sp_name"),
names_from = lipids,
values_from = n,
values_fill = 0) %>%
mutate(total = sum(no, yes)) %>%
pivot_longer(cols = c(no, yes),
names_to = "lipids",
values_to = "count") %>%
mutate(percent = count/total,
collection_date = lubridate::as_date(collection_date),
lipids = fct_relevel(lipids, "no", "yes")) %>%
ungroup() %>%
complete(collection_date, nesting(sp_name, lipids), fill = list(percent = 1)) %>%
mutate(percent = if_else(is.na(total) & lipids == "yes", 0, percent)) %>%
ggplot(aes(x = collection_date, y = percent, fill = lipids)) +
facet_wrap(sp_name~., ncol = 1) +
geom_area() +
scale_fill_manual(values = lipid_cols) +
scale_y_continuous(breaks = c(0,1)) +
labs(x = "Collection Date",
y = "Proportion",
fill = "Lipids\nPresent") +
theme_minimal(base_size = 20) +
theme(panel.grid = element_blank(),
axis.ticks = element_line())

Temperature Variability
Lake Champlain is highly seasonal, with both average temperatures and
temperature variability changing throughout the year. These patterns in
the experienced thermal environment may drive the observed variation in
copepod thermal limits. However, the time period affecting copepod
thermal limits is unknown. Depending the on the duration of time
considered, there are large changes in the experienced environment, in
particular regarding the temperature range and variance. Consider for
example three time periods: the day of collection, one week prior to
collection, and four weeks prior to collection. While the overall
pattern is similar, we can see that, unsurprisingly, considering longer
periods of time results in larger ranges and slightly changes the
pattern of variance experienced.
## Defining the function to get predictor values for periods of different lengths
get_predictors = function(daily_values, raw_temp, n_days){
prefix = str_replace_all(xfun::numbers_to_words(n_days), pattern = " ", replacement = "-")
mean_values = daily_values %>%
ungroup() %>%
mutate(mean_max = slide_vec(.x = max_temp, .f = mean, .before = n_days, .complete = T),
mean_min = slide_vec(.x = min_temp, .f = mean, .before = n_days, .complete = T),
mean_range = slide_vec(.x = range_temp, .f = mean, .before = n_days, .complete = T)) %>%
select(date, mean_max, mean_min, mean_range) %>%
rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))
period_values = raw_temp %>%
mutate(mean = slide_index_mean(temp, i = date, before = days(n_days),
na_rm = T),
max = slide_index_max(temp, i = date, before = days(n_days),
na_rm = T),
min = slide_index_min(temp, i = date, before = days(n_days),
na_rm = T),
med = slide_index_dbl(temp, .i = date, .before = days(n_days),
na_rm = T, .f = median),
var = slide_index_dbl(temp, .i = date, .before = days(n_days),
.f = var),
range = max - min) %>%
select(-temp) %>%
distinct() %>%
rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))%>%
inner_join(mean_values, by = c("date")) %>%
drop_na()
return(period_values)
}
Organisms are unlikely to acclimate instantaneously to changes in
temperature. To explore the potential temporal window these copepods are
responding to, we examined the correlation between thermal limits and
summaries of the thermal environment over different periods of time. For
each species (inclusive of all sexes and stages), we examined the
correlation between CTmax and one of nine representations of the thermal
environment calculated for periods of time from 1 to 60 days before
collection. These parameters include the overall maximum, minimum,
median, and mean temperature for the period of time, the temperature
range and variance during this time, and the mean daily temperature
maximum, minimum, and range. We also examined the correlation between
CTmax and the temperature recorded at the time of collection.
Shown below are the correlation coefficients for these relationships.
Each facet shows the relationship for a different parameter, plotted
against the duration of the time period before collection.
corr_vals %>%
mutate(parameter = fct_relevel(parameter, c("min", "max", "range",
"mean", "med", "var",
"mean_min", "mean_max", "mean_range"))) %>%
ggplot(aes(x = duration, y = correlation, colour = sp_name)) +
facet_wrap(.~parameter) +
geom_hline(yintercept = 0) +
geom_point(size = 0.9) +
geom_line(linewidth = 1.5) +
scale_colour_manual(values = species_cols) +
labs(x = "Duration (days)",
y = "Correlation",
colour = "Species") +
theme_matt_facets()

This table contains the top three factors for each species (based on
correlation coefficient).
Shown here is a graphical summary of the duration of the best
predictors for each species. Note that for the two Leptodiaptomids,
collection temperature had the largest correlation coefficient so
duration is zero. This representation highlights that there is variation
across the community not only in the potential driver (e.g. minimum
vs. maximum temperatures) but also in the duration of time. This
variation is not grouped by season (the winter and summer communities
both have representative species apparently responding to short and long
durations).
duration_plot = corr_vals %>%
filter(sig == "Sig.") %>%
drop_na(correlation) %>%
group_by(sp_name) %>%
arrange(desc(correlation)) %>%
slice_head(n = 1) %>%
ungroup() %>%
mutate("num" = row_number(),
sp_name = fct_reorder(sp_name, duration, .fun = mean, .desc = T)) %>%
arrange(sp_name) %>%
select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, num) %>%
ggplot(aes(x = Species, y = Duration, fill = Predictor, group = num)) +
geom_bar(stat = "identity", width = 0.5, position = position_dodge(width = 0.6),
colour = "black") +
scale_fill_manual(values = c("coll_temp" = "black", "max" = "white", "min" = "grey")) +
labs(x = "",
y = "Duration \n(days)") +
theme_matt() +
theme(axis.text.x = element_blank())
correlation_coef_plot = corr_vals %>%
filter(sig == "Sig." | parameter == "coll_temp") %>%
drop_na(correlation) %>%
group_by(sp_name) %>%
filter(parameter == "coll_temp" | correlation == max(correlation)) %>%
arrange(sp_name, parameter) %>%
mutate("num" = row_number()) %>%
select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, num) %>%
mutate(Predictor = if_else(Predictor == "coll_temp", Predictor, "best")) %>%
ungroup() %>%
mutate(Species = fct_reorder(Species, Duration, .fun = max, .desc = T)) %>%
ggplot(aes(x = Species, y = Correlation, fill = Predictor, group = num)) +
geom_bar(stat = "identity", width = 0.5, position = position_dodge(width = 0.6),
colour = "black") +
labs(y = "Correlation \nCoefficient",
fill = "Correlate") +
scale_fill_manual(values = c("coll_temp" = "black", "best" = "white")) +
scale_y_continuous(breaks = c(0, 1), limits = c(0,1)) +
theme_matt() +
theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))
ggarrange(duration_plot, correlation_coef_plot, nrow = 2, legend = "right",
heights = c(0.4, 0.6))

Trait Variation
Shown below are the clutch size distributions for the three
diaptomiid species, which produce egg sacs that allow for easy
quantification of fecundity.
full_data %>%
drop_na(fecundity) %>%
ggplot(aes(x = fecundity, fill = sp_name_sub)) +
facet_wrap(.~sp_name_sub, ncol = 1) +
geom_histogram(binwidth = 2) +
scale_fill_manual(values = species_cols) +
labs(x = "Fecundity (# Eggs)") +
theme_matt_facets() +
theme(legend.position = "none")

One of the main aims of this project is to examine the patterns and
processes driving variation in upper thermal limits across these species
of copepods.
Variation with temperature
We expect one of the primary drivers of copepod thermal limits to be
temperature, as individuals acclimate to seasonal changes. Shown below
are the seasonal patterns of when copepods were included in CTmax
measurements (a proxy for the season of occurrence), and thermal limits
for each species plotted against the temperature at the time of
collection. We generally see an increase in thermal limits with
increasing collection temperature.
sp_ctmax_temp = full_data %>%
filter(sp_name != "Osphranticum labronectum") %>%
mutate(sp_name = as.factor(sp_name),
sp_name = fct_reorder(sp_name, ctmax, .desc = T)) %>%
ggplot(aes(x = collection_temp, y = ctmax, colour = sp_name)) +
facet_wrap(sp_name~.) +
geom_smooth(method = "lm", se = F, linewidth = 1.5, colour = "grey30") +
geom_point(size = 2, alpha = 0.4) +
labs(x = "Collection Temp. (°C)",
y = "CTmax (°C)") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "none")
ggarrange(sample_dates_plot, sp_ctmax_temp, nrow = 1,
labels = "AUTO")

The interaction between seasonal changes in temperature and the
acclimation of thermal limits likely affects vulnerability of each
species to warming. Shown below are warming tolerance values for each
species, calculated as the difference between individual CTmax and the
temperature at the time of collection. All species maintained some
degree of buffer between environmental temperatures and upper thermal
limits, but L. minutus appears to approach its upper thermal
limit during the warmest collections during the summer.
Also shown below is the relationship between fecundity (the number of
eggs contained in a clutch) for the three diaptomid species. For the two
Leptodiaptomus species, there is no relationship between clutch size and
temperature, while there appears to be a general increase in clutch size
with temperature in the Skistodiaptomus species.
wt_temp = full_data %>%
filter(sp_name != "Osphranticum labronectum") %>%
ggplot(aes(x = collection_temp, y = warming_tol, colour = sp_name)) +
geom_point(size = 3,
alpha = 0.3) +
geom_smooth(method = "lm", linewidth = 3) +
labs(x = "Collection Temperature (°C)",
y = "Warming Tolerance (°C)",
colour = "Species") +
ylim(0,30) +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "none")
eggs_temp = full_data %>%
filter(sp_name != "Osphranticum labronectum") %>%
ggplot(aes(x = collection_temp, y = fecundity, colour = sp_name)) +
geom_point(size = 3,
alpha = 0.3) +
geom_smooth(method = "lm", linewidth = 3) +
labs(x = "Collection Temperature (°C)",
y = "Fecundity (# Eggs)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
ggarrange(wt_temp, eggs_temp,
common.legend = T, legend = "right")

# Copepods spent several days in lab during experiments. Shown below are the CTmax residuals (taken from a model of CTmax against collection temperature) plotted against the time spent in lab before measurements were made. Individual regressions are shown for the residuals against days in lab for each collection. We can see clearly that thermal limits are fairly stable over time.
# ggplot(ctmax_resids, aes(x = days_in_lab, y = resids, colour = sp_name, group = collection_date)) +
# facet_wrap(sp_name~.) +
# geom_point(size = 4, alpha = 0.5) +
# geom_smooth(method = "lm", se = F, linewidth = 1) +
# #scale_x_continuous(breaks = c(0:5)) +
# labs(x = "Days in lab",
# y = "CTmax Residuals") +
# scale_colour_manual(values = species_cols) +
# theme_matt_facets() +
# theme(legend.position = "none")
model_data = full_data %>%
drop_na(size, ctmax) %>%
filter(sp_name != "Osphranticum labronectum") %>%
mutate(temp_cent = scale(collection_temp, center = T, scale = F),
size_cent = scale(size, center = T, scale = F))
minimal.model = lme4::lmer(data = model_data,
ctmax ~ sp_name + sex + temp_cent +
(1|days_in_lab))
full.model = lme4::lmer(data = filter(model_data, sp_name != "Osphranticum labronectum"),
ctmax ~ sp_name*sex*temp_cent +
(1|days_in_lab))
drop1(full.model, test = "Chisq")
## Single term deletions
##
## Model:
## ctmax ~ sp_name * sex * temp_cent + (1 | days_in_lab)
## npar AIC LRT Pr(Chi)
## <none> 5280.1
## sp_name:sex:temp_cent 10 5281.0 20.887 0.0219 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
performance::test_performance(minimal.model, full.model)
## Name | Model | BF | df | df_diff | Chi2 | p
## ----------------------------------------------------------------
## minimal.model | lmerMod | | 11 | | |
## full.model | lmerMod | 0.001 | 38 | 27.00 | 180.70 | < .001
## Models were detected as nested (in terms of fixed parameters) and are compared in sequential order.
performance::check_model(full.model)

car::Anova(full.model, type = "III")
## Analysis of Deviance Table (Type III Wald chisquare tests)
##
## Response: ctmax
## Chisq Df Pr(>Chisq)
## (Intercept) 4619.014 1 < 2.2e-16 ***
## sp_name 344.724 5 < 2.2e-16 ***
## sex 51.233 2 7.495e-12 ***
## temp_cent 53.731 1 2.299e-13 ***
## sp_name:sex 10.611 10 0.38866
## sp_name:temp_cent 39.512 5 1.873e-07 ***
## sex:temp_cent 31.961 2 1.147e-07 ***
## sp_name:sex:temp_cent 20.616 10 0.02393 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
sp_ctmax = emmeans::emmeans(full.model, specs = "sp_name") %>%
data.frame() %>%
select(sp_name, "species_ctmax" = emmean)
model_coefs = emmeans::emtrends(full.model, var = "temp_cent", specs = "sp_name") %>%
data.frame() %>%
inner_join(sp_ctmax)
ctmax_resids = model_data %>%
mutate(resids = residuals(full.model))
arr_combined = synth_arr %>%
filter(measure == "upper" & mean_lim > 20) %>%
select("group" = genus, arr, mean_lim) %>%
mutate("dataset" = "synthesis") %>%
bind_rows(
select(model_coefs, "group" = sp_name, 'arr' = temp_cent.trend, 'mean_lim' = species_ctmax)
) %>%
mutate(dataset = if_else(is.na(dataset), "new data", "synthesis"),
group = fct_reorder(group, arr, .desc = T))
ggplot(arr_combined, aes(x = mean_lim, y = arr)) +
geom_smooth(method = "lm", se = F,
linewidth = 2, colour = "grey30") +
geom_point(data = filter(arr_combined, dataset != "new data"),
size = 4, colour = "grey") +
geom_point(data = filter(arr_combined, dataset == "new data"),
aes(colour = group),
size = 4) +
scale_colour_manual(values = species_cols) +
labs(x = "Thermal Limit",
y = "ARR",
colour = "Species") +
theme_matt() +
theme(legend.position = "right")

Sex and stage variation in thermal limits
Previous sections have generally lumped juvenile, female, and male
individuals together. There may be important stage- or sex-specific
differences in CTmax though. For all species but Osphranticum, we have
measurements for individuals in different stages and of different
sexes.
sex_sample_sizes = full_data %>%
group_by(sp_name, sex) %>%
summarise(num = n()) %>%
pivot_wider(id_cols = sp_name,
names_from = sex,
values_from = num,
values_fill = 0) %>%
select("Species" = sp_name, "Juvenile" = juvenile, "Female" = female, "Male" = male)
knitr::kable(sex_sample_sizes, align = "c")
| Epischura lacustris |
37 |
45 |
20 |
| Leptodiaptomus minutus |
12 |
273 |
39 |
| Leptodiaptomus sicilis |
31 |
356 |
95 |
| Limnocalanus macrurus |
4 |
43 |
39 |
| Osphranticum labronectum |
0 |
1 |
0 |
| Senecella calanoides |
13 |
21 |
8 |
| Skistodiaptomus sp |
15 |
232 |
28 |
Across group comparisons show that there are generally no differences
in thermal limits (represented here as the residuals from a CTmax ~
collection_temp x species linear regression), with the exception of
Senecella males, which may have lower thermal limits (although sample
sizes are very small in this group).
# ctmax_resids %>%
# filter(sp_name != "Osphranticum labronectum") %>%
# ggplot(aes(x = sex, y = resids, colour = sp_name)) +
# facet_wrap(sp_name~.) +
# geom_jitter(width = 0.1, alpha = 0.5) +
# geom_boxplot(width = 0.4, fill = NA, colour = "black",
# linewidth = 1, outlier.colour = NA) +
# scale_colour_manual(values = species_cols) +
# theme_matt_facets()
model2_data = model_data %>%
filter(sex == "female",
pathogen != "uncertain",
dev_eggs != "uncertain",
lipids != "uncertain") %>%
mutate(pathogens = fct_relevel(pathogen, "no", "spot", "cloudy", "other"))
other_factor_model = lmer(data = model2_data,
ctmax~sp_name * collection_temp + dev_eggs + pathogen + lipids + (1|days_in_lab))
drop1(other_factor_model, scope = ~., test = "Chisq")
## Single term deletions
##
## Model:
## ctmax ~ sp_name * collection_temp + dev_eggs + pathogen + lipids +
## (1 | days_in_lab)
## npar AIC LRT Pr(Chi)
## <none> 3601.6
## sp_name 5 3804.2 212.619 < 2.2e-16 ***
## collection_temp 0 3601.6 0.000
## dev_eggs 1 3602.0 2.391 0.1220
## pathogen 3 3629.4 33.832 2.149e-07 ***
## lipids 1 3600.0 0.416 0.5189
## sp_name:collection_temp 5 3635.7 44.139 2.171e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
reduced_factors_model = lmer(data = model2_data,
ctmax~sp_name * collection_temp + pathogen + (1|days_in_lab))
performance::check_model(reduced_factors_model)

emmeans::emmeans(reduced_factors_model, spec = "pathogen") %>% emmeans::contrast(method="trt.vs.ctrl",ref="no") %>% plot() +
geom_vline(xintercept = 0) +
labs(x = "Difference (°C)",
y = "Comparison") +
theme_matt()

Trait Correlations and Trade-offs
A relationship between size and upper thermal limits has been
suggested in a wide range of other taxa. Shown below are the measured
upper thermal limits plotted against prosome length. The overall
relationship (inclusive of all species) is shown as the black line in
the background. Regressions for each individual species are also shown.
Across the entire assemblage, there is a strong decrease in thermal
limits with increasing size.
full_data %>%
#filter(sex == "female") %>%
ggplot( aes(x = size, y = ctmax, colour = sp_name)) +
geom_point(size = 2, alpha = 0.3) +
geom_smooth(data = full_data,
aes(x = size, y = ctmax),
method = "lm",
colour ="black",
linewidth = 2.5) +
labs(x = "Length (mm)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")

Shown here is the relationship for each species individually.
full_data %>%
#filter(sex == "female") %>%
group_by(sp_name) %>% filter(n() >2) %>% filter(!str_detect(sp_name, pattern = "kindti")) %>%
ggplot( aes(x = size, y = ctmax, colour = sp_name)) +
facet_wrap(sp_name~., scales = "free", nrow = 2) +
geom_point(size = 2, alpha = 0.8) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
labs(x = "Length (mm)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "none")

Shown below is the relationship between mean size and mean thermal
limits for females of each species. We see that larger species within
the community tend to have a lower thermal limit than smaller
species.
full_data %>%
group_by(sp_name, sex) %>%
summarize(mean_ctmax = mean(ctmax, na.rm = T),
mean_size = mean(size, na.rm = T)) %>%
#filter(sex == "female") %>%
ggplot(aes(x = mean_size, y = mean_ctmax)) +
geom_smooth(method = "lm", se = F, linewidth = 2, colour = "black") +
geom_point(aes(colour = sp_name, shape = sex),
size = 5) +
labs(x = "Length (mm)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")

Shown here is the relationship between fecundity and size, showing
the classic pattern of increasing egg production with increasing
size.
size_fecund_plot = ctmax_resids %>%
drop_na(fecundity) %>%
ggplot(aes(x = size, y = fecundity, colour = sp_name)) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
geom_point(size = 2, alpha = 0.5) +
labs(x = "Prosome length (mm)",
y = "Fecundity (# Eggs)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
Individuals may also allocate energy to different fitness related
traits, prioritizing reproductive output over environmental tolerance,
for example. Shown below is the relationship between CTmax residuals
(again, controlling for the effects of collection temperature) against
fecundity. We can see clearly that individuals with increased fecundity
are not decreasing thermal limits, suggesting that there is no energetic
trade-off between these traits.
ctmax_fecund_plot = ctmax_resids %>%
drop_na(fecundity) %>%
ggplot(aes(x = resids, y = fecundity, colour = sp_name)) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
geom_point(size = 2, alpha = 0.5) +
labs(x = "CTmax Residuals (°C)",
y = "Fecundity (# Eggs)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
ggarrange(size_fecund_plot, ctmax_fecund_plot, ncol = 1, common.legend = T, legend = "right")

Previous studies have shown that the magnitude of the size-fecundity
correlation may be environmentally-dependent. This is not visible is the
data from these collections.
corr_data = full_data %>%
drop_na(fecundity) %>%
filter(sp_name %in% c("Leptodiaptomus sicilis",
"Leptodiaptomus minutus",
"Skistodiaptomus sp")) %>%
group_by(collection_date, collection_temp, sp_name) %>%
summarise(size_fec_corr = cor(size, fecundity),
n = n(),
mean_fecundity = mean(fecundity)) %>%
filter(n >= 3) %>%
ungroup() %>%
group_by(sp_name) %>%
mutate(temp_cent = scale(collection_temp, scale = F))
ggplot(corr_data, aes(x = temp_cent, y = size_fec_corr, colour = sp_name)) +
facet_wrap(sp_name~., nrow = 3) +
geom_hline(yintercept = 0) +
geom_point(size = 3) +
geom_smooth(method = "lm", linewidth = 2) +
scale_color_manual(values = species_cols) +
labs(x = "Temperature (centered)",
y = "Correlation Coefficient") +
coord_cartesian(ylim = c(-1, 1)) +
theme_matt_facets() +
theme(legend.position = "none")

# ggplot(corr_data, aes(x = size_fec_corr)) +
# facet_wrap(sp_name~., nrow = 3) +
# geom_histogram(binwidth = 0.2)
Other patterns in variation
Leptodiaptomus sicilis is the most abundant species during
the winter. There was a large shift in the size of mature females
towards the end of December. These large and small individuals are the
same species (confirmed via COI sequencing), suggesting this shift may
instead reflect a transition from one generation to another. This size
difference may be caused by differences in the developmental
environments. For example, individuals developing in January grow up at
very low temperatures, and therefore may reach larger sizes. These
individuals over-summer in deep waters, then re-emerge in October and
produce a new generation. Water temperatures are still fairly high
through November, which results in a generation of smaller individuals.
These individuals mature in time to produce a new generation in
January.
full_data %>%
filter(sp_name == "Leptodiaptomus sicilis") %>%
filter(sex != "juvenile") %>%
group_by(collection_date) %>%
mutate(size_center = scale(size, center = T, scale = F)) %>%
ggplot(aes(y = factor(collection_date), x = size, fill = collection_temp)) +
facet_wrap(sex~.) +
geom_density_ridges(bandwidth = 0.04) +
geom_vline(xintercept = 0.89) +
labs(x = "Size (mm)",
y = "Date",
fill = "Coll. Temp. (°C)") +
theme_matt() +
theme(legend.position = "right",
axis.text.y = element_text(size = 12))

A similar, but less distinct pattern can be observed in L. minutus
individuals as well.
full_data %>%
filter(sp_name == "Leptodiaptomus minutus") %>%
filter(sex != "juvenile") %>%
ggplot(aes(y = factor(collection_date), x = size, fill = collection_temp)) +
facet_wrap(sex~.) +
geom_density_ridges(bandwidth = 0.04) +
geom_vline(xintercept = 0.69) +
labs(x = "Size (mm)",
y = "Date",
fill = "Coll. Temp. (°C)") +
coord_cartesian(xlim = c(0.5,0.9)) +
theme_matt() +
theme(legend.position = "right",
axis.text.y = element_text(size = 12))

Distribution Lag Non-Linear Model (DLNM approach)
Distributed lag models examine a response variable, measured at
multiple time points, as a function of the lagged occurrence of some
predictor variable (response y at time t as a function of predictor
x(t-lag). This method utilizes a bi-dimensional dose-lag-response
function, which essentially examines not only the dose effect, but the
effect of the timing of the dose.
# Run this code, save the product, and then just read in the temp lag data object. Takes too long to run each time this document is knit.
# lag_temps = temp_data %>%
# group_by(date, hour) %>%
# summarize("mean_temp" = mean(temp, na.rm = T)) %>%
# ungroup() %>%
# mutate(point_num = row_number())
#
# uniq_days = length(unique(lag_temps$date))
#
# g = gam(mean_temp ~ s(point_num, bs="cr", k=uniq_days + 10),
# method = "REML",
# data = lag_temps)
#
# points = seq(1, nrow(lag_temps), length.out = length(lag_temps$hour))
#
# df.res = df.residual(g)
#
# pred_temps = predict(g, newdata = lag_temps, type = "response", se.fit = TRUE)
#
# lag_temps = lag_temps %>%
# mutate(trend_T = pred_temps$fit,
# trend_se = pred_temps$se.fit,
# temp_diff = mean_temp - trend_T)
#
# write.csv(lag_temps, file = "./Output/Data/lag_temps.csv", row.names = F)
dlnm_data = full_data %>%
filter(sex == "female") %>%
filter(sp_name %in% c(
"Leptodiaptomus sicilis",
"Leptodiaptomus minutus",
"Skistodiaptomus sp"
)) %>%
select(collection_date, collection_temp, sp_name, ctmax) %>%
group_by(collection_date, collection_temp, sp_name) %>%
summarise(mean_ctmax = mean(ctmax, na.rm = T),
sample = n())
temp_data %>%
group_by(date) %>%
summarise(mean_temp = mean(temp),
max_temp = max(temp, na.rm = T)) %>%
right_join(dlnm_data, by = join_by("date" == "collection_date")) %>%
ggplot(aes(x = max_temp, y = mean_ctmax)) +
facet_wrap(.~sp_name) +
geom_smooth(method = "gam") +
geom_point() +
labs(x = "Max Daily Temp. (°C)",
y = "Mean CTmax (°C)") +
theme_matt_facets() +
theme(strip.text.x = element_text(size = 12))

sp_list = unique(dlnm_data$sp_name)
for(lag_species in sp_list){
dlnm_data_sp = dlnm_data %>%
filter(sp_name == lag_species)
# We need to estimate a matrix of exposure histories for each observation. This contains the series of exposures at each lag (l) for each of the n observations, constrained between l0 (minimum lag) and L (max lag).
dates = dlnm_data_sp$collection_date # For each of these dates, make a vector of the past 30 days (including the day of collection). NOTE: Don't use 'unique' dates here since some collections had multiple species
exp_hist_z = data.frame()
exp_hist_trend = data.frame()
for(d in dates){
history = lag_temps %>%
filter(date <= d & date > d - 10) %>%
arrange(desc(date), desc(hour)) %>%
mutate(lag = row_number() - 1) %>%
select(lag, mean_temp, temp_diff)
z_vec = scale(history$mean_temp)[,1]
names(z_vec) = history$lag
trend_vec = history$temp_diff
names(trend_vec) = history$lag
exp_hist_z = bind_rows(exp_hist_z, z_vec)
exp_hist_trend = bind_rows(exp_hist_trend, trend_vec)
}
#print(max(exp_hist_trend, na.rm = T))
# The cross-basis function from dlnm will use the class of the x parameter to determine what to do. In our case, we need to provide it with the matrix of exposure histories for reach observation (row) and lag (column).
cb_temps = crossbasis(exp_hist_trend, lag = c(0,dim(exp_hist_trend)[2]-1),
argvar =list(fun="cr",df=3),
arglag=list(fun="cr",df=3,intercept=T))
#summary(cb_temps)
penalized_mat <- cbPen(cb_temps)
#fitting GAM
lag.gam = gam(data = dlnm_data_sp,
mean_ctmax ~ collection_temp + cb_temps,
method = "GCV.Cp",
paraPen=list(cb_temps=penalized_mat))
# summary(lag.gam)
# AIC(lag.gam)
#estimation of exposures effects
#default plots
pred_gam_Zs<-crosspred(cb_temps, lag.gam,
cumul=F, cen=0, ci.level = 0.95,
at=seq(-4,4, 0.1))
plot(pred_gam_Zs, "contour", main = lag_species)
#
# plot(pred_gam_Zs, border = 2, cumul=F,
# theta=110,phi=20,ltheta=-80)
plot(pred_gam_Zs, "slices",
var = c(3,-3),
lag = c(1,200),
col = 2)
}






Hindcasting vulnerability with different acclimation scenarios
Using the observed thermal limit data, we can produce a hindcast of
thermal stress for Lake Champlain copepods. For these initial assays, we
will define thermal stress as any time when maximum daily water
temperature is within 5°C of copepod CTmax or higher (i.e. warming
tolerance is less than 5°C). We will use three different scenarios: 1)
each species has a unique but fixed thermal limit (average measured
CTmax), 2) species have unique thermal limits and are able to acclimate
(constant ARR across all species used to predict CTmax based on average
daily temperatures), and 3) species have unique thermal limits and
species-specific acclimation (CTmax predicted using whichever
environmental factor and duration is the strongest candidate for driving
acclimation - from the correlation analysis). In all cases, data is
filtered to just thermal limits of adult females.
Scenario 1
mean_ctmax = full_data %>%
filter(sex == "female") %>%
group_by(sp_name) %>%
summarize("mean_ctmax" = mean(ctmax)) %>%
arrange(mean_ctmax)
knitr::kable(mean_ctmax)
| Senecella calanoides |
22.04400 |
| Limnocalanus macrurus |
22.88927 |
| Leptodiaptomus sicilis |
29.15785 |
| Leptodiaptomus minutus |
31.53916 |
| Epischura lacustris |
31.85441 |
| Skistodiaptomus sp |
35.67407 |
| Osphranticum labronectum |
36.31250 |
# # Constructs the URL for the full temperature data set; RUN THIS ONCE
# hind_url = constructNWISURL(siteNumbers = siteNumber, parameterCd = parameterCd, service = "uv")
#
# hind_temp_data = importWaterML1(hind_url, asDateTime = T) %>%
# mutate("date" = as.Date(dateTime)) %>%
# select(date, "temp" = X_00010_00000)
#
# write.table(x = hind_temp_data, file = "hindcast_temps.csv", row.names = F, sep = ",")
# ggplot(hind_temp_data, aes(x = date, y = temp)) +
# geom_line(linewidth = 0.1) +
# labs(x = "Date",
# y = "Water Temperature (°C)") +
# theme_matt()
In the simplest scenario, species thermal limits are static through
time, represented by the average CTmax of adult female copepods. In this
scenario, only three of the seven observed species are exposed to
thermal stress (temperatures within 5°C of CTmax). Temperatures
approached the thermal limit of Leptodiaptomus sicilis on a
handful of days. By contrast, Senecella calanoides and
Limnocalanus macrurus were both exposed to substantial thermal
stress throughout a large portion of the year, likely explaining why
these species are absent from the community for the summer and fall
periods.
hind1_data = hind_temp_data %>%
group_by(date) %>%
summarize("daily_max" = max(temp),
"daily_mean" = mean(temp),) %>%
bind_cols(pivot_wider(mean_ctmax, names_from = sp_name, values_from = mean_ctmax)) %>%
pivot_longer(cols = c(-date, -daily_max, -daily_mean),
names_to = "species",
values_to = "mean_ctmax") %>%
mutate(lim_diff = mean_ctmax - daily_max) %>%
mutate(doy = yday(date),
"method" = "No_acclimation")
hind_daily_temp_data = hind_temp_data %>%
ungroup() %>%
group_by(date) %>%
summarise(mean_temp = mean(temp),
med_temp = median(temp),
var_temp = var(temp),
min_temp = min(temp),
max_temp = max(temp)) %>%
mutate("range_temp" = max_temp - min_temp)
#table(hind1_data$species)
hind1_data %>%
filter(lim_diff <= 5) %>%
ggplot(aes(x = doy, y = lim_diff, colour = species)) +
geom_hline(yintercept = 0) +
geom_hline(yintercept = 5,
colour = "grey") +
geom_point(alpha = 0.5) +
geom_smooth(se = F) +
labs(x = "Day of Year",
y = "Predicted Warming Tolerance \n(°C Above Daily Max)") +
theme_matt() +
theme(legend.position = "right")

Scenario 2
In the second scenario, thermal limits vary within and between
species. A simple model is used to predict species thermal limits based
on mean daily temperature (CTmax as a function of species and collection
temperature, but without the interaction between these two factors).
These predicted thermal limits are then compared against the maximum
daily temperature to estimate thermal stress, as in Scenario 1.
Including this simple form of acclimation in the model reduced the
degree of thermal stress for each species, eliminating it entirely for
Leptodiaptomus sicilis. Note that the magnitude of the
predicted stress is low enough that removing the 5°C buffer around the
predicted thermal limits would actually limit predicted thermal stress
to just a few days for Senecella calanoides.
hindcast_model1 = lm(data = filter(full_data, sex == "female"),
ctmax ~ collection_temp + sp_name)
hind2_data = hind_temp_data %>%
group_by(date) %>%
summarize("collection_temp" = mean(temp),
"daily_max" = max(temp)) %>%
bind_cols(
pivot_wider(mean_ctmax,
names_from = sp_name,
values_from = mean_ctmax)) %>%
pivot_longer(cols = c(-date, -daily_max, -collection_temp),
names_to = "sp_name",
values_to = "mean_ctmax") %>%
select(-mean_ctmax) %>%
mutate("pred_ctmax" = predict.lm (hindcast_model1, newdata = .)) %>%
select(date, "daily_mean" = collection_temp, daily_max, "species" = sp_name, pred_ctmax) %>%
mutate(lim_diff = pred_ctmax - daily_max) %>%
#filter(lim_diff <= 0) %>%
mutate(doy = yday(date),
"method" = "Constant_acclimation")
# ggplot(hind2_data, aes(x = daily_mean, y = pred_ctmax, colour = species)) +
# geom_smooth(method = "lm")
# table(hind2_data$species)
hind2_data %>%
filter(lim_diff <= 5) %>%
ggplot(aes(x = doy, y = lim_diff, colour = species)) +
geom_hline(yintercept = 0) +
geom_hline(yintercept = 5,
colour = "grey") +
geom_point(alpha = 0.5) +
geom_smooth() +
labs(x = "Day of Year",
y = "Predicted Warming Tolerance \n(°C Above Daily Max)") +
theme_matt() +
theme(legend.position = "right")

Scenario 3
The final scenario allows the environmental variable used to predict
CTmax to vary between species. For species observed in fewer than 5
collections, we use the same approach as in Scenario 2. For species
observed in more than 5 collections, however, the factor with the
strongest correlation with CTmax is used to predict thermal limits.
These factors are included below.
hind_preds = corr_vals %>%
filter(sig == "Sig.") %>%
drop_na(correlation) %>%
group_by(sp_name) %>%
arrange(desc(correlation)) %>%
slice_head(n = 1) %>%
select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, "P-Value" = p.value)
knitr::kable(hind_preds, align = "c")
| Epischura lacustris |
max |
29 |
0.9147764 |
0.0000000 |
| Leptodiaptomus minutus |
coll_temp |
0 |
0.7732711 |
0.0000000 |
| Leptodiaptomus sicilis |
coll_temp |
0 |
0.2833554 |
0.0000001 |
| Limnocalanus macrurus |
min |
8 |
0.5496742 |
0.0000000 |
| Senecella calanoides |
max |
19 |
0.5038896 |
0.0006688 |
| Skistodiaptomus sp |
max |
2 |
0.7972819 |
0.0000000 |
hind3_data = hind2_data %>% # Contains data for species that won't change from scenario 2
filter(!(species %in% corr_vals$sp_name))
preds_to_pull = hind_preds %>%
select(Species, Predictor, Duration)
for(i in 1:length(preds_to_pull$Species)){
duration = preds_to_pull$Duration[i]
if(duration == 0){ #The prior day temperature metrics should be used
predictors = hind_daily_temp_data %>%
mutate(date = date)
parameter = "mean_temp" #using mean temperature as a proxy for collection temp
model_data = full_data %>%
filter(sp_name %in% preds_to_pull$Species[i]) %>%
filter(sex == "female") %>%
mutate(collection_date = as_date(collection_date)) %>%
inner_join(predictors, join_by(collection_date == date)) %>%
select(ctmax, contains(parameter))
if(dim(model_data)[2] == 2){
hind.model = lm(data = model_data,
ctmax ~ .)
sp_data = predictors %>%
select(date, contains(parameter)) %>%
mutate(pred_ctmax = predict(hind.model, newdata = .)) %>%
select(date, pred_ctmax) %>%
inner_join(hind_daily_temp_data, by = c("date")) %>%
mutate("species" = preds_to_pull$Species[i],
"doy" = yday(date),
lim_diff = pred_ctmax - max_temp) %>%
select(date, daily_mean = mean_temp, daily_max = max_temp, species, pred_ctmax, lim_diff, doy)
hind3_data = bind_rows(hind3_data, sp_data)
}else{
print(c(unique(sp_data$species), "Too many columns selected"))
}
}
if(duration > 0){
#Neither the prior day nor day of metrics should be used; use duration as n_days
predictors = get_predictors(daily_values = hind_daily_temp_data,
raw_temp = hind_temp_data,
n_days = duration)
parameter = preds_to_pull$Predictor[i]
model_data = full_data %>%
filter(sp_name %in% preds_to_pull$Species[i]) %>%
filter(sex == "female") %>%
mutate(collection_date = as_date(collection_date)) %>%
left_join(predictors, join_by(collection_date == date)) %>%
select(ctmax, contains(paste("day_", parameter, sep = "")))
if(dim(model_data)[2] == 2){
hind.model = lm(data = model_data,
ctmax ~ .)
sp_data = predictors %>%
select(date, contains(parameter)) %>%
mutate(pred_ctmax = predict(hind.model, newdata = .)) %>%
select(date, pred_ctmax) %>%
inner_join(hind_daily_temp_data, by = c("date")) %>%
mutate("species" = preds_to_pull$Species[i],
"doy" = yday(date),
lim_diff = pred_ctmax - max_temp) %>%
select(date, daily_mean = mean_temp, daily_max = max_temp, species, pred_ctmax, lim_diff, doy)
hind3_data = bind_rows(hind3_data, sp_data)
}else{
print(c(unique(sp_data$species), "Too many columns selected"))
}
}
}
hind3_data = hind3_data %>%
mutate("method" = "Variable_acclimation")
This third approach did not affect the predicted patterns in
Limnocalanus or Senecella (neither species has been
observed in enough collections to estimate the effects of different
environmental factors). Changing the acclimation approach did affect
patterns in thermal limits in the other species though. The figure below
shows how predicted warming tolerance varies over the year in the seven
species, based on the three different prediction methods. In general,
constant thermal limits (the ‘no acclimation’ method) resulted in larger
warming tolerance during the winter and lower warming tolerance during
the summer, although this effect was small in most species.
synthesis = bind_rows(
select(hind1_data, date, doy, daily_mean, daily_max, species, "pred_ctmax" = mean_ctmax, lim_diff, method),
select(hind2_data, date, doy, daily_mean, daily_max, species, pred_ctmax, lim_diff, method),
select(hind3_data, date, doy, daily_mean, daily_max, species, pred_ctmax, lim_diff, method)) %>%
mutate(method = fct_relevel(method, "No_acclimation", "Constant_acclimation", "Variable_acclimation")) %>%
filter(!(species == "Osphranticum labronectum" & method == "Variable_acclimation"))
climatology = synthesis %>%
group_by(species, doy, method) %>%
summarise("mean_diff" = mean(lim_diff),
"min_diff" = min(lim_diff),
"max_diff" = max(lim_diff)) %>%
mutate(method = fct_relevel(method, "No_acclimation", "Constant_acclimation", "Variable_acclimation"))
acc_effects = synthesis %>%
pivot_wider(id_cols = c(date, species, doy),
names_from = method,
values_from = lim_diff) %>%
mutate("const_acc_effect" = Constant_acclimation - No_acclimation,
"var_acc_effect" = Variable_acclimation - No_acclimation)
ggplot(synthesis, aes(x = doy, y = lim_diff, colour = method)) +
facet_wrap(species~.) +
geom_hline(yintercept = 0) +
geom_hline(yintercept = 5, colour = "grey") +
geom_point(alpha = 0.1) +
labs(x = "Day of Year",
y = "Predicted Warming Tolerance (°C Above Daily Max)") +
guides(colour = guide_legend(override.aes = list(alpha = 1))) +
theme_matt_facets(base_size = 18) +
theme(strip.text.x.top = element_text(size = 10))

wt_hindcast_summary = synthesis %>%
mutate("year" = year(date)) %>%
group_by(species, year, method) %>%
summarise("min_wt" = min(lim_diff),
"max_wt" = max(lim_diff)) %>%
pivot_longer(cols = c(min_wt, max_wt),
names_to = "metric",
values_to = "wt") %>%
group_by(species, method, metric) %>%
summarise("mean_wt" = mean(wt))
wt_hindcast_summary %>%
filter(metric == "min_wt") %>%
ggplot(aes(x = method, y = mean_wt, group = species, colour = species)) +
#facet_wrap(.~metric, scales = "free_y") +
geom_hline(yintercept = 0) +
geom_hline(yintercept = 5) +
geom_line(linewidth = 2) +
geom_point(size = 3) +
labs(x = "Scenario",
y = "Mean Yearly Minimum WT (°C)") +
scale_color_manual(values = species_cols) +
theme_matt_facets() +
theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

LS0tCnRpdGxlOiBTZWFzb25hbGl0eSBpbiBMYWtlIENoYW1wbGFpbiBDb3BlcG9kIFRoZXJtYWwgTGltaXRzCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9VCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBlY2hvID0gRn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBrbml0cjo6aXNfaHRtbF9vdXRwdXQoKSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucGF0aCA9ICIuLi9GaWd1cmVzL21hcmtkb3duLyIsCiAgZGV2ID0gYygicG5nIiwgInBkZiIpLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgY29sbGFwc2UgPSBUCikKCnRoZW1lX21hdHQgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgZ2dwdWJyOjp0aGVtZV9wdWJyKGJhc2VfZmFtaWx5PSJzYW5zIikgJStyZXBsYWNlJSAKICAgIHRoZW1lKAogICAgICBwYW5lbC5iYWNrZ3JvdW5kICA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9ibGFuaygpLAogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IG1pZF90ZXh0LCBsaW5laGVpZ2h0ID0gMS4xKSwKICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZGFya190ZXh0KSwKICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtaWRfdGV4dCksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDMsIDAsIDAsIDApLCAibW0iKSksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsIDUsIDAsIDApLCAibW0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1iYXNlX3NpemUgKiAwLjkpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDAuOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMC4yNSwgMC4yNSwgMC4yNSwgMC4yNSwiY20iKQogICAgKQp9Cgp0aGVtZV9tYXR0X2ZhY2V0cyA9IGZ1bmN0aW9uKGJhc2Vfc2l6ZSA9IDE4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgdGhlbWVfYncoYmFzZV9mYW1pbHk9InNhbnMiKSAlK3JlcGxhY2UlIAogICAgdGhlbWUoCiAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgIHBhbmVsLmJhY2tncm91bmQgID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwgCiAgICAgIHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksCiAgICAgIGxlZ2VuZC5rZXkgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KGNvbG91ciA9IG1pZF90ZXh0LCBsaW5laGVpZ2h0ID0gMS4xKSwKICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUpLAogICAgICB0aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS41LAogICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBkYXJrX3RleHQpLAogICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IG1pZF90ZXh0KSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMywgMCwgMCwgMCksICJtbSIpKSwKICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJnaW4gPSB1bml0KGMoMCwgNSwgMCwgMCksICJtbSIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuZ2xlID0gOTApLAogICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPWJhc2Vfc2l6ZSAqIDAuOSksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMC45LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhY2UgPSAiYm9sZCIpLAogICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLjI1LCAwLjI1LCAwLjI1LCAwLjI1LCJjbSIpCiAgICApCn0KCnNwZWNpZXNfY29scyA9IGMoIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiID0gIiNmZmQwMjkiLAogICAgICAgICAgICAgICAgICJMZXB0b2RpYXB0b211cyBtaW51dHVzIGp1dmVuaWxlIiA9ICIjZTNkOGFmIiwKICAgICAgICAgICAgICAgICAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyBtYWxlIiA9ICIjZmZlODk2IiwKICAgICAgICAgICAgICAgICAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIgPSAiI0Q4NkYyOSIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMgbWFsZSIgPSAiI0UyOEMwMCIsCiAgICAgICAgICAgICAgICAgIlNraXN0b2RpYXB0b211cyBzcCIgPSAiI0M1QzM1QSIsCiAgICAgICAgICAgICAgICAgIlNraXN0b2RpYXB0b211cyBzcCBtYWxlIiA9ICIjZDlkODkzIiwgCiAgICAgICAgICAgICAgICAgIlNraXN0b2RpYXB0b211cyBzcCBqdXZlbmlsZSIgPSAiI2U2ZTZhYSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIGp1dmVuaWxlIiA9ICJwbHVtMSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIG1hbGUiID0gInBsdW0zIiwgCiAgICAgICAgICAgICAgICAgIkVwaXNjaHVyYSBsYWN1c3RyaXMiID0gInBsdW00IiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyIgPSAic2t5Ymx1ZTQiLCAKICAgICAgICAgICAgICAgICAiTGltbm9jYWxhbnVzIG1hY3J1cnVzIG1hbGUiID0gInNreWJsdWUzIiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyBqdXZlbmlsZSIgPSAic2t5Ymx1ZSIsIAogICAgICAgICAgICAgICAgICJTZW5lY2VsbGEgY2FsYW5vaWRlcyIgPSAiZGFya3NlYWdyZWVuMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkgbWFsZSIgPSAibGlnaHRibHVlMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkiID0gImxpZ2h0Ymx1ZTQiLAogICAgICAgICAgICAgICAgICJMZXB0b2RvcmEga2luZHRpIGp1dmVuaWxlIiA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iID0gImxpZ2h0Y29yYWwiKQpgYGAKCiMjIENvcGVwb2QgQ29sbGVjdGlvbgoKQ29wZXBvZHMgd2VyZSBjb2xsZWN0ZWQgYXQgYXBwcm94aW1hdGVseSB3ZWVrbHkgaW50ZXJ2YWxzIGZyb20gTGFrZSBDaGFtcGxhaW4gKEJ1cmxpbmd0b24gRmlzaGluZyBQaWVyKS4gUGxhbmt0b24gd2FzIGNvbGxlY3RlZCBmcm9tIHRoZSB0b3AgMyBtZXRlcnMgdXNpbmcgYSAyNTAgdW0gbWVzaCBuZXQuIAoKYGBge3J9CiMgIyBMYWtlIENoYW1wbGFpbiBuZWFyIEJ1cmxpbmd0b24sIFZUCiMgc2l0ZU51bWJlciA9ICIwNDI5NDUwMCIKIyBDaGFtcGxhaW5JbmZvID0gcmVhZE5XSVNzaXRlKHNpdGVOdW1iZXIpCiMgcGFyYW1ldGVyQ2QgPSAiMDAwMTAiCiMgc3RhcnREYXRlID0gIjIwMjMtMDEtMDEiCiMgZW5kRGF0ZSA9ICIyMDI0LTUtMjAiCiMgI3N0YXRDZCA9IGMoIjAwMDAxIiwgIjAwMDAyIiwiMDAwMDMiLCAiMDAwMTEiKSAjIDEgLSBtYXgsIDIgLSBtaW4sIDMgPSBtZWFuCiMgCiMgIyBDb25zdHJ1Y3RzIHRoZSBVUkwgZm9yIHRoZSBkYXRhIHdhbnRlZCB0aGVuIGRvd25sb2FkcyB0aGUgZGF0YQojIHVybCA9IGNvbnN0cnVjdE5XSVNVUkwoc2l0ZU51bWJlcnMgPSBzaXRlTnVtYmVyLCBwYXJhbWV0ZXJDZCA9IHBhcmFtZXRlckNkLAojICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnREYXRlID0gc3RhcnREYXRlLCBlbmREYXRlID0gZW5kRGF0ZSwgc2VydmljZSA9ICJ1diIpCiMgCiMgcmF3X3RlbXBzID0gaW1wb3J0V2F0ZXJNTDEodXJsLCBhc0RhdGVUaW1lID0gVCkgJT4lCiMgICBtdXRhdGUoImRhdGUiID0gYXMuRGF0ZShkYXRlVGltZSksCiMgICAgICAgICAgImhvdXIiID0gaG91cihkYXRlVGltZSkpICU+JQojICAgc2VsZWN0KGRhdGVUaW1lLCB0el9jZCwgZGF0ZSwgaG91ciwgZGVnQyA9IFhfMDAwMTBfMDAwMDApCiMgCiMgdGVtcF9kYXRhID0gIHJhd190ZW1wcyAlPiUKIyAgIHNlbGVjdChkYXRlLCBob3VyLCAidGVtcCIgPSBkZWdDKQojIAojIHdyaXRlLmNzdih0ZW1wX2RhdGEsIGZpbGUgPSAiLi9PdXRwdXQvRGF0YS9jaGFtcGxhaW5fdGVtcHMuY3N2Iiwgcm93Lm5hbWVzID0gRikKYGBgCgpDb2xsZWN0aW9ucyBiZWdhbiBpbiBsYXRlIE1heSAyMDIzLiBTZXZlcmFsIGdhcHMgYXJlIHByZXNlbnQsIGJ1dCBjb2xsZWN0aW9ucyBoYXZlIGNvbnRpbnVlZCBhdCByb3VnaGx5IHdlZWtseSBpbnRlcnZhbHMgc2luY2UgdGhlbi4gQ29wZXBvZHMgZnJvbSBgciBsZW5ndGgodW5pcXVlKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX2RhdGUpKWAgY29sbGVjdGlvbnMgd2VyZSB1c2VkIHRvIG1ha2UgYSB0b3RhbCBvZiBgciBkaW0oZnVsbF9kYXRhKVsxXWAgdGhlcm1hbCBsaW1pdCBtZWFzdXJlbWVudHMuIE92ZXIgdGhpcyB0aW1lIHBlcmlvZCwgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZXMgcmFuZ2VkIGZyb20gYHIgcGFzdGUobWluKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX3RlbXApLCAiIHRvICIsIG1heChmdWxsX2RhdGEkY29sbGVjdGlvbl90ZW1wKSwgc2VwID0gIiIpYMKwQy4gICAgIAoKVGhlcmUgaXMgc3Vic3RhbnRpYWwgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzIGFjcm9zcyB0aGUgc3BlY2llcyBjb2xsZWN0ZWQuIFRoZXJlIGlzIGFsc28gc29tZSBkZWdyZWUgb2YgdmFyaWF0aW9uIHdpdGhpbiB0aGUgc3BlY2llcywgd2l0aCB0aGVybWFsIGxpbWl0cyBpbmNyZWFzaW5nIHNsaWdodGx5IGR1cmluZyB0aGUgc3VtbWVyLiAgICAKCmBgYHtyIG1haW4tZmlnLWN0bWF4LXRpbWVzZXJpZXMsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD01fQojIyBEYWlseSB2YWx1ZXMgZm9yIHRoZSBwZXJpb2QgZXhhbWluZWQgYnkgZGF0YXNldApjb2xsZWN0aW9uX2NvbmRpdGlvbnMgPSB0ZW1wX2RhdGEgJT4lCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCksCiAgICAgICAgICAgIG1lZF90ZW1wID0gbWVkaWFuKHRlbXApLAogICAgICAgICAgICB2YXJfdGVtcCA9IHZhcih0ZW1wKSwgCiAgICAgICAgICAgIG1pbl90ZW1wID0gbWluKHRlbXApLCAKICAgICAgICAgICAgbWF4X3RlbXAgPSBtYXgodGVtcCkpICU+JSAKICBtdXRhdGUoInJhbmdlX3RlbXAiID0gbWF4X3RlbXAgLSBtaW5fdGVtcCwKICAgICAgICAgZGF0ZSA9IGFzLkRhdGUoZGF0ZSkpICU+JSAKICB1bmdyb3VwKCkgJT4lICAKICBmaWx0ZXIoZGF0ZSA+PSAobWluKGFzLkRhdGUoZnVsbF9kYXRhJGNvbGxlY3Rpb25fZGF0ZSkpIC0gNykpICU+JSAKICBsZWZ0X2pvaW4odW5pcXVlKHNlbGVjdChmdWxsX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSksIGJ5ID0gam9pbl9ieShkYXRlID09IGNvbGxlY3Rpb25fZGF0ZSkpCgojIyBNZWFuIGZlbWFsZSB0aGVybWFsIGxpbWl0cyBmb3IgZWFjaCBzcGVjaWVzLCBncm91cGVkIGJ5IGNvbGxlY3Rpb24Kc3BlY2llc19zdW1tYXJpZXMgPSBmdWxsX2RhdGEgJT4lICAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSAlPiUgIAogIHN1bW1hcmlzZSgibWVhbl9jdG1heCIgPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgInNhbXBsZV9zaXplIiA9IG4oKSwKICAgICAgICAgICAgImN0bWF4X3N0X2VyciIgPSAoc2QoY3RtYXgpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAiY3RtYXhfdmFyIiA9IHZhcihjdG1heCksIAogICAgICAgICAgICAibWVhbl9zaXplIiA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgICJzaXplX3N0X2VyciIgPSAoc2Qoc2l6ZSkgLyBzcXJ0KHNhbXBsZV9zaXplKSksCiAgICAgICAgICAgICJzaXplX3ZhciIgPSB2YXIoc2l6ZSkpICU+JSAgCiAgdW5ncm91cCgpICU+JSAKICBjb21wbGV0ZShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUpICU+JSAKICBhcnJhbmdlKGRlc2Moc2FtcGxlX3NpemUpKQoKYWR1bHRfc3VtbWFyaWVzID0gZnVsbF9kYXRhICU+JSAgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSAlPiUgIAogIHN1bW1hcmlzZSgibWVhbl9jdG1heCIgPSBtZWFuKGN0bWF4KSwKICAgICAgICAgICAgInNhbXBsZV9zaXplIiA9IG4oKSwKICAgICAgICAgICAgImN0bWF4X3N0X2VyciIgPSAoc2QoY3RtYXgpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAiY3RtYXhfdmFyIiA9IHZhcihjdG1heCksIAogICAgICAgICAgICAibWVhbl9zaXplIiA9IG1lYW4oc2l6ZSksCiAgICAgICAgICAgICJzaXplX3N0X2VyciIgPSAoc2Qoc2l6ZSkgLyBzcXJ0KHNhbXBsZV9zaXplKSksCiAgICAgICAgICAgICJzaXplX3ZhciIgPSB2YXIoc2l6ZSkpICU+JSAgCiAgdW5ncm91cCgpICU+JSAKICBjb21wbGV0ZShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUpICU+JSAKICBhcnJhbmdlKGRlc2Moc2FtcGxlX3NpemUpKQoKCnRzZXJpZXNfZGF0YSA9IGZ1bGxfZGF0YSAlPiUgCiAgbXV0YXRlKHNwX25hbWUgPSBmY3RfcmVvcmRlcihzcF9uYW1lLCBjdG1heCwgLmRlc2MgPSBUKSkKCmdncGxvdCgpICsgCiAgZ2VvbV92bGluZShkYXRhID0gdW5pcXVlKHNlbGVjdCh0c2VyaWVzX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSkpLCAKICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpKSwKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5OTAiLAogICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGNvbGxlY3Rpb25fY29uZGl0aW9ucywgCiAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IG1lYW5fdGVtcCksCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIAogICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogICMgZ2VvbV9lcnJvcmJhcihkYXRhID0gc3BlY2llc19zdW1tYXJpZXMsCiAgIyAgICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLAogICMgICAgICAgICAgICAgICAgICAgeW1pbiA9IG1lYW5fY3RtYXggLSBjdG1heF9zdF9lcnIsIHltYXggPSBtZWFuX2N0bWF4ICsgY3RtYXhfc3RfZXJyLAogICMgICAgICAgICAgICAgICAgICAgY29sb3VyID0gc3BfbmFtZSksCiAgIyAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwKICAjICAgICAgICAgICAgICAgd2lkdGggPSA1LCBsaW5ld2lkdGggPSAxKSArCiAgIyBnZW9tX3BvaW50KGRhdGEgPSBhZHVsdF9zdW1tYXJpZXMsIAogICMgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IG1lYW5fY3RtYXgsIGNvbG91ciA9IHNwX25hbWUsIHNpemUgPSBzYW1wbGVfc2l6ZSkpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gdHNlcmllc19kYXRhLCAKICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNwX25hbWUpLAogICAgICAgICAgICAgc2l6ZSA9IDIsIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKHdpZHRoID0gMSwgaGVpZ2h0ID0gMCkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkRhdGUiLCAKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIiwKICAgICAgIHNpemUgPSAiU2FtcGxlIFNpemUiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpsYWtlX3RlbXBzID0gZ2dwbG90KCkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGNvbGxlY3Rpb25fY29uZGl0aW9ucywgCiAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IG1lYW5fdGVtcCksCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIAogICAgICAgICAgICBsaW5ld2lkdGggPSAxKSArIAogIGxhYnMoeCA9ICJEYXRlIiwgCiAgICAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwgCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIsCiAgICAgICBzaXplID0gIlNhbXBsZSBTaXplIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKClRlbXBlcmF0dXJlcyBvYnNlcnZlZCBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uIGNsb3NlbHkgcmVzZW1ibGVkIHRoZSBtYXhpbXVtIGRhaWx5IHRlbXBlcmF0dXJlIGZyb20gdGhlIHRlbXBlcmF0dXJlIHNlbnNvciBkYXRhLiBNYXhpbXVtIHRlbXBlcmF0dXJlIHdhcyB1c2VkIGFzIGEgcHJveHkgaW5zdGVhZCBvZiBtZWFuIHRlbXBlcmF0dXJlIGFzIGNvbGxlY3Rpb25zIHdlcmUgdXN1YWxseSBtYWRlIGR1cmluZyBhZnRlcm5vb25zIG9yIGVhcmx5IGV2ZW5pbmdzLCBqdXN0IGZvbGxvd2luZyB0aGUgd2FybWVzdCBwYXJ0IG9mIHRoZSBkYXkuIAoKYGBge3Igc3VwcC1maWctdGVtcC1hY2MsIGZpZy53aWR0aCA9IDYsIGZpZy5oZWlnaHQ9Nn0KY29sbGVjdGlvbl9jb25kaXRpb25zICU+JSAKICBkcm9wX25hKGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBnZ3Bsb3QoYWVzKHggPSBtYXhfdGVtcCwgeSA9IGNvbGxlY3Rpb25fdGVtcCkpICsgCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxLAogICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEsIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoNSwxNSwyNSkpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoNSwxNSwyNSkpICsgCiAgbGFicyh4ID0gIk1heC4gVGVtcC4gZnJvbSBTZW5zb3IgKMKwQykiLAogICAgICAgeSA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIikgKyAKICB0aGVtZV9tYXR0KCkKYGBgCgpgYGB7ciBtaXNjLXJvdW5kLXN1bW1hcnktMiwgZmlnLndpZHRoPTExLCBmaWcuaGVpZ2h0PTExLCBpbmNsdWRlID0gRn0KZ2dwbG90KCkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAKICAgICAgICAgICAgICAgYyhtYXgoZnVsbF9kYXRhJGNvbGxlY3Rpb25fdGVtcCksCiAgICAgICAgICAgICAgICAgbWluKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX3RlbXApKSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTYwIiwKICAgICAgICAgICAgIGxpbmV3aWR0aCA9IGMoMiwxKSwgCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKyAKICBnZW9tX2JhcihkYXRhID0gdW5pcXVlKHNlbGVjdChmdWxsX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wKSksIAogICAgICAgICAgIGFlcyh4ID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgICBzdGF0ID0gImlkZW50aXR5IiwKICAgICAgICAgICBmaWxsID0gImdyZXkzMCIpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgIGFlcyh4ID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY3RtYXgpLAogICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9qaXR0ZXIod2lkdGggPSAwLjcsIGhlaWdodCA9IDApLAogICAgICAgICAgICAgY29sb3VyID0gImdyZXkzMCIsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSkgKyAKICB5bGltKC0zLCA0MCkgKyAKICBjb29yZF9wb2xhcihzdGFydCA9IDApICsgCiAgdGhlbWVfdm9pZCgpCmBgYAoKClNpemUgYWxzbyB2YXJpZWQsIGJ1dCBwcmltYXJpbHkgYmV0d2VlbiByYXRoZXIgdGhhbiB3aXRoaW4gc3BlY2llcy4gCgpgYGB7ciBzdXBwLWZpZy1zaXplLXRpbWVzZXJpZXMsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD01fQpnZ3Bsb3QoKSArIAogIGdlb21fdmxpbmUoZGF0YSA9IHVuaXF1ZShzZWxlY3QoZnVsbF9kYXRhLCBjb2xsZWN0aW9uX2RhdGUpKSwgCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSksCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTkwIiwKICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBjb2xsZWN0aW9uX2NvbmRpdGlvbnMsIAogICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIHkgPSBtZWFuX3RlbXApLAogICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCAKICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICAjIGdlb21fZXJyb3JiYXIoZGF0YSA9IHNwZWNpZXNfc3VtbWFyaWVzLAogICMgICAgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgCiAgIyAgICAgICAgICAgICAgICAgICB5bWluID0gbWVhbl9jdG1heCAtIGN0bWF4X3N0X2VyciwgeW1heCA9IG1lYW5fY3RtYXggKyBjdG1heF9zdF9lcnIsCiAgIyAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBzcF9uYW1lKSwKICAjICAgICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpLAogICMgICAgICAgICAgICAgICB3aWR0aCA9IDUsIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gYWR1bHRfc3VtbWFyaWVzLCAKICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gbWVhbl9zaXplICogNDAsIGNvbG91ciA9IHNwX25hbWUsIHNpemUgPSBzYW1wbGVfc2l6ZSksCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKAogICAgbmFtZSA9ICJUZW1wZXJhdHVyZSIsICMgRmVhdHVyZXMgb2YgdGhlIGZpcnN0IGF4aXMKICAgIHNlYy5heGlzID0gc2VjX2F4aXMofi4vNDAsIG5hbWU9IlByb3NvbWUgTGVuZ3RoIChtbSkiKSwgIyBBZGQgYSBzZWNvbmQgYXhpcyBhbmQgc3BlY2lmeSBpdHMgZmVhdHVyZXMKICAgIGJyZWFrcyA9IGMoMCw1LDEwLDE1LDIwLDI1LDMwKQogICkgKyAKICBsYWJzKHggPSAiRGF0ZSIsIAogICAgICAgeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsIAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKYGBge3IgbWlzYy10cmFpdC1kb3ktZmVhdHVyZSwgZmlnLndpZHRoID0gMTQsIGZpZy5oZWlnaHQgPSA3LCBpbmNsdWRlID0gRn0KI1Nob3duIGJlbG93IGlzIENUbWF4IGFuZCBib2R5IHNpemUgZm9yIHRoZSBzcGVjaWVzIHdpdGggdGhlIG1vc3QgZGF0YSAoKlNraXN0b2RpYXB0b211cyosICpMLiBtaW51dHVzKiwgKkwuIHNpY2lsaXMqLCBhbmQgKkVwaXNjaHVyYSopLCBwbG90dGVkIGFnYWluc3QgdGhlIGRheSBvZiB0aGUgeWVhciBmb3IgZWFjaCBzZXgvc3RhZ2Ugc2VwYXJhdGVseS4gCgpjdG1heF9mZWF0dXJlID0gZnVsbF9kYXRhICU+JSAgCiAgbXV0YXRlKGRveSA9IHlkYXkoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgYygiU2tpc3RvZGlhcHRvbXVzIG9yZWdvbmVuc2lzIiwgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiLCAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIsICJFcGlzY2h1cmEgbGFjdXN0cmlzIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfZ3JpZChzcF9uYW1lfnNleCkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBsYWJzKHggPSAiRGF5IG9mIHRoZSBZZWFyIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKc2l6ZV9mZWF0dXJlID0gZnVsbF9kYXRhICU+JSAgCiAgbXV0YXRlKGRveSA9IHlkYXkoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgYygiU2tpc3RvZGlhcHRvbXVzIG9yZWdvbmVuc2lzIiwgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiLCAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIsICJFcGlzY2h1cmEgbGFjdXN0cmlzIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBzaXplLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF9ncmlkKHNwX25hbWV+c2V4KSArIAogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgdGhlIFllYXIiLCAKICAgICAgIHkgPSAiU2l6ZSAobW0pIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZ2dhcnJhbmdlKGN0bWF4X2ZlYXR1cmUsIHNpemVfZmVhdHVyZSwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJub25lIikKYGBgCgpgYGB7ciBzcC1vY2N1cmVuY2VzLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpzYW1wbGVfZGF0ZXNfcGxvdCA9IGZ1bGxfZGF0YSAlPiUgIAogIGZpbHRlcihzcF9uYW1lICE9ICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iKSAlPiUgCiAgbXV0YXRlKHNwX25hbWUgPSBhcy5mYWN0b3Ioc3BfbmFtZSksCiAgICAgICAgIHNwX25hbWUgPSBmY3RfcmVvcmRlcihzcF9uYW1lLCBjdG1heCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsdWJyaWRhdGU6OmFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSwgCiAgICAgICAgICAgICB5ID0gc3BfbmFtZSwgZmlsbCA9IHNwX25hbWUpKSArIAogICMgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYXNfZGF0ZSgKICAjICAgYygiMjAyMy0wNS0wMSIsCiAgIyAgICAgIjIwMjMtMDktMDEiLAogICMgICAgICIyMDI0LTAxLTAxIiwKICAjICAgICAiMjAyNC0wNS0wMSIpKSwKICAjICAgY29sb3VyID0gImdyZXkiLAogICMgICBsaW5ld2lkdGggPSAxKSArIAogIGdlb21fZGVuc2l0eV9yaWRnZXMoYmFuZHdpZHRoID0gMzAsCiAgICAgICAgICAgICAgICAgICAgICBqaXR0ZXJlZF9wb2ludHMgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgIHBvaW50X3NoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgICAgICBwb2ludF9zaXplID0gMSwKICAgICAgICAgICAgICAgICAgICAgIHBvaW50X2NvbG91ciA9ICJncmV5MzAiLAogICAgICAgICAgICAgICAgICAgICAgcG9pbnRfYWxwaGEgPSAwLjgsCiAgICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IDAuOCwKICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fcG9pbnRzX2ppdHRlcigKICAgICAgICAgICAgICAgICAgICAgICAgaGVpZ2h0ID0gMC4xLCB3aWR0aCA9IDApKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBzY2FsZV94X2RhdGUoZGF0ZV9icmVha3MgPSAiMyBtb250aHMiLAogICAgICAgICAgICAgICBkYXRlX2xhYmVscyA9ICIlYiIpICsgCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBsdWJyaWRhdGU6OmFzX2RhdGUoYygiMjAyMy0wNi0wOCIsICIyMDI0LTA1LTA4IikpKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgWWVhciIsIAogICAgICAgeSA9ICJTcGVjaWVzIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICAjdGhlbWVfcmlkZ2VzKGdyaWQgPSBUKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAoKVGhlIHNhbXBsZXMgY2FwdHVyZWQgdGhlIGJyb2FkIHNlYXNvbmFsIGNoYW5nZXMgaW4gY2FsYW5vaWQgY29wZXBvZCBjb21tdW5pdHkgY29tcG9zaXRpb24gaW4gdGhlIGxha2UuIFdlIG5vdGUsIGhvd2V2ZXIsIHRoYXQgcmFyZSBzcGVjaWVzIChlLmcuICpTZW5lY2VsbGEqIGFuZCAqTGltbm9jYWxhbnVzKikgd2VyZSBvZnRlbiBwcmVmZXJlbnRpYWxseSBzYW1wbGVkLCBzbyBhcmUgb3Zlci1yZXByZXNlbnRlZCBpbiB0aGUgZGF0YSBzZXQuIAoKYGBge3Igc3VwcC1maWctc3AtcHJvcHMsIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gNSwgaW5jbHVkZSA9IEZ9CmFkdWx0X3N1bW1hcmllcyAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUoY29sbGVjdGlvbl9udW0gPSBhcy5udW1lcmljKGZhY3Rvcihjb2xsZWN0aW9uX2RhdGUpKSkgJT4lIAogIGdyb3VwX2J5KGNvbGxlY3Rpb25fZGF0ZSkgJT4lICAKICBhcnJhbmdlKGNvbGxlY3Rpb25fZGF0ZSkgJT4lIAogIHNlbGVjdChzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fbnVtLCBzYW1wbGVfc2l6ZSkgJT4lIAogIG11dGF0ZShzYW1wbGVfc2l6ZSA9IHJlcGxhY2VfbmEoc2FtcGxlX3NpemUsIDApKSAlPiUgCiAgbXV0YXRlKHRvdGFsID0gc3VtKHNhbXBsZV9zaXplKSwKICAgICAgICAgcGVyY2VudGFnZSA9IHNhbXBsZV9zaXplIC8gdG90YWwsCiAgICAgICAgIGNvbGxlY3Rpb25fZGF0ZSA9IGx1YnJpZGF0ZTo6YXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl9kYXRlLCB5ID0gcGVyY2VudGFnZSwgZmlsbCA9IHNwX25hbWUpKSArIAogIGdlb21fYXJlYSgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBjKDAsMSkpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gRGF0ZSIsIAogICAgICAgeSA9ICJQcm9wb3J0aW9uIiwgCiAgICAgICBmaWxsID0gIlNwZWNpZXMiKSArIAogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKCkpCmBgYAoKVGhyb3VnaG91dCB0aGUgc2Vhc29uLCB0aGUgcHJldmFsZW5jZSBvZiB2YXJpb3VzIHVuaWRlbnRpZmllZCBwYXRob2dlbnMgYWxzbyB2YXJpZWQsIHdpdGggdmVyeSBsaXR0bGUgaW5mZWN0aW9uIG9ic2VydmVkIGR1cmluZyB0aGUgV2ludGVyIGFuZCBTcHJpbmcuIAoKYGBge3Igc3VwcC1maWctcGF0aG9nZW4tcHJvcHMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTV9CnBhdGhvZ2VuX2NvbHMgPSBjKCJubyIgPSAiZ3JleTk1IiwgImNsb3VkeSIgPSAiaG9uZXlkZXczIiwgInNwb3QiID0gImFudGlxdWV3aGl0ZTMiLCAib3RoZXIiID0gInRvbWF0bzMiKQoKZnVsbF9kYXRhICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBkZXZfZWdncywgcGF0aG9nZW4sIGxpcGlkcywgc3BfbmFtZSwgc2V4KSAlPiUgCiAgZ3JvdXBfYnkoKSAlPiUgCiAgZmlsdGVyKHNleCAhPSAianV2ZW5pbGUiKSAlPiUgCiAgZ3JvdXBfYnkoY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgY291bnQocGF0aG9nZW4pICU+JSAKICBmaWx0ZXIocGF0aG9nZW4gIT0gInVuY2VydGFpbiIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gImNvbGxlY3Rpb25fZGF0ZSIsIAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBwYXRob2dlbiwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuLAogICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCkgJT4lIAogIG11dGF0ZSh0b3RhbCA9IHN1bShubywgY2xvdWR5LCBzcG90LCBvdGhlcikpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMobm8sIGNsb3VkeSwgc3BvdCwgb3RoZXIpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXRob2dlbiIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudC90b3RhbCwKICAgICAgICAgY29sbGVjdGlvbl9kYXRlID0gbHVicmlkYXRlOjphc19kYXRlKGNvbGxlY3Rpb25fZGF0ZSksCiAgICAgICAgIHBhdGhvZ2VuID0gZmN0X3JlbGV2ZWwocGF0aG9nZW4sICJubyIsICJjbG91ZHkiLCAic3BvdCIsICJvdGhlciIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl9kYXRlLCB5ID0gcGVyY2VudCwgZmlsbCA9IHBhdGhvZ2VuKSkgKyAKICBnZW9tX2FyZWEoKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHBhdGhvZ2VuX2NvbHMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwxKSkgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBEYXRlIiwgCiAgICAgICB5ID0gIlByb3BvcnRpb24iLCAKICAgICAgIGZpbGwgPSAiUGF0aG9nZW4iKSArIAogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9saW5lKCkpCmBgYAoKVGhlIHRyYW5zcGFyZW50IGJvZGllcyBvZiB0aGVzZSBjb3BlcG9kcyBhbHNvIGFsbG93ZWQgdXMgdG8gZXhhbWluZSBzZWFzb25hbCBwYXR0ZXJucyBpbiBsaXBpZCByZXNlcnZlcyBhbmQgaW4gdGhlIHByb2R1Y3Rpb24gb2YgZWdncy4gTWF0dXJpbmcgb29jeXRlcyBhcmUgdmlzaWJsZSBpbiBmZW1hbGUgY29wZXBvZHMgYmVmb3JlIHRoZXkgYXJlIHJlbGVhc2VkLiBUaGVyZSB3YXMgbm8gc3Ryb25nIHNlYXNvbmFsIGN5Y2xlIGluIHRoZSBwcm9kdWN0aW9uIG9mIHRoZXNlIGVnZ3MgaW4gYW55IHNwZWNpZXMsIGFuZCBpbnN0ZWFkLCBmZW1hbGVzIHdlcmUgcmVwcm9kdWN0aXZlbHkgYWN0aXZlIHRocm91Z2hvdXQgdGhlaXIgcmVzcGVjdGl2ZSBzZWFzb25zIG9mIG9jY3VyZW5jZS4gCgpgYGB7ciBzdXBwLWZpZy1kZXZlZ2dzLXByb3BzLCBmaWcuaGVpZ2h0ID0gMTUsIGZpZy53aWR0aCA9IDh9CmRldl9lZ2dzX2NvbHMgPSBjKCJubyIgPSAiZ3JleTk1IiwgInllcyIgPSAibGlnaHRibHVlMyIpCgpmdWxsX2RhdGEgJT4lIAogIHNlbGVjdChjb2xsZWN0aW9uX2RhdGUsIGRldl9lZ2dzLCBwYXRob2dlbiwgbGlwaWRzLCBzcF9uYW1lLCBzZXgpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKHNleCAhPSAianV2ZW5pbGUiKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgY291bnQoZGV2X2VnZ3MpICU+JSAKICBmaWx0ZXIoZGV2X2VnZ3MgIT0gInVuY2VydGFpbiIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYygiY29sbGVjdGlvbl9kYXRlIiwgInNwX25hbWUiKSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IGRldl9lZ2dzLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG4sCiAgICAgICAgICAgICAgdmFsdWVzX2ZpbGwgPSAwKSAlPiUgCiAgbXV0YXRlKHRvdGFsID0gc3VtKG5vLCB5ZXMpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKG5vLCB5ZXMpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJkZXZfZWdncyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAiY291bnQiKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSBjb3VudC90b3RhbCwKICAgICAgICAgY29sbGVjdGlvbl9kYXRlID0gbHVicmlkYXRlOjphc19kYXRlKGNvbGxlY3Rpb25fZGF0ZSksCiAgICAgICAgIGRldl9lZ2dzID0gZmN0X3JlbGV2ZWwoZGV2X2VnZ3MsICJubyIsICJ5ZXMiKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgY29tcGxldGUoY29sbGVjdGlvbl9kYXRlLCBuZXN0aW5nKHNwX25hbWUsIGRldl9lZ2dzKSwgZmlsbCA9IGxpc3QocGVyY2VudCA9IDEpKSAlPiUgCiAgbXV0YXRlKHBlcmNlbnQgPSBpZl9lbHNlKGlzLm5hKHRvdGFsKSAmIGRldl9lZ2dzID09ICJ5ZXMiLCAwLCBwZXJjZW50KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fZGF0ZSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBkZXZfZWdncykpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIG5jb2wgPSAxKSArIAogIGdlb21fYXJlYSgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gZGV2X2VnZ3NfY29scykgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gYygwLDEpKSArIAogIGxhYnMoeCA9ICJDb2xsZWN0aW9uIERhdGUiLCAKICAgICAgIHkgPSAiUHJvcG9ydGlvbiIsIAogICAgICAgZmlsbCA9ICJEZXZlbG9waW5nIFxuRWdncyIpICsgCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAyMCkgKyAKICB0aGVtZShwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MgPSBlbGVtZW50X2xpbmUoKSkKYGBgCgpUaGUgcHJlc2VuY2Ugb2YgbGlwaWRzIHZhcmllZCBhY3Jvc3Mgc3BlY2llcywgd2l0aCBvbmx5ICpMLiBtaW51dHVzKiwgKkwuIHNpY2lsaXMqLCBhbmQgKkxpbW5vY2FsYW51cyogcmVndWxhcmx5IHBvc3Nlc3NpbmcgbGlwaWQgc3RvcmVzLiAKCmBgYHtyIHN1cHAtZmlnLWxpcGlkcy1wcm9wcywgZmlnLmhlaWdodCA9IDE1LCBmaWcud2lkdGggPSA4fQpsaXBpZF9jb2xzID0gYygibm8iID0gImdyZXk5NSIsICJ5ZXMiID0gInNpZW5uYTIiKQoKZnVsbF9kYXRhICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBkZXZfZWdncywgcGF0aG9nZW4sIGxpcGlkcywgc3BfbmFtZSwgc2V4KSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lIAogIGZpbHRlcihzZXggIT0gImp1dmVuaWxlIikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIGNvbGxlY3Rpb25fZGF0ZSkgJT4lIAogIGNvdW50KGxpcGlkcykgJT4lIAogIGZpbHRlcihsaXBpZHMgIT0gInVuY2VydGFpbiIpICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYygiY29sbGVjdGlvbl9kYXRlIiwgInNwX25hbWUiKSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IGxpcGlkcywgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBuLAogICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCkgJT4lIAogIG11dGF0ZSh0b3RhbCA9IHN1bShubywgeWVzKSkgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYyhubywgeWVzKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAibGlwaWRzIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJjb3VudCIpICU+JSAKICBtdXRhdGUocGVyY2VudCA9IGNvdW50L3RvdGFsLAogICAgICAgICBjb2xsZWN0aW9uX2RhdGUgPSBsdWJyaWRhdGU6OmFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSwKICAgICAgICAgbGlwaWRzID0gZmN0X3JlbGV2ZWwobGlwaWRzLCAibm8iLCAieWVzIikpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGNvbXBsZXRlKGNvbGxlY3Rpb25fZGF0ZSwgbmVzdGluZyhzcF9uYW1lLCBsaXBpZHMpLCBmaWxsID0gbGlzdChwZXJjZW50ID0gMSkpICU+JSAKICBtdXRhdGUocGVyY2VudCA9IGlmX2Vsc2UoaXMubmEodG90YWwpICYgbGlwaWRzID09ICJ5ZXMiLCAwLCBwZXJjZW50KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fZGF0ZSwgeSA9IHBlcmNlbnQsIGZpbGwgPSBsaXBpZHMpKSArIAogIGZhY2V0X3dyYXAoc3BfbmFtZX4uLCBuY29sID0gMSkgKyAKICBnZW9tX2FyZWEoKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGxpcGlkX2NvbHMpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwxKSkgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBEYXRlIiwgCiAgICAgICB5ID0gIlByb3BvcnRpb24iLCAKICAgICAgIGZpbGwgPSAiTGlwaWRzXG5QcmVzZW50IikgKyAKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDIwKSArIAogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfbGluZSgpKQpgYGAKCgojIyBUZW1wZXJhdHVyZSBWYXJpYWJpbGl0eQpMYWtlIENoYW1wbGFpbiBpcyBoaWdobHkgc2Vhc29uYWwsIHdpdGggYm90aCBhdmVyYWdlIHRlbXBlcmF0dXJlcyBhbmQgdGVtcGVyYXR1cmUgdmFyaWFiaWxpdHkgY2hhbmdpbmcgdGhyb3VnaG91dCB0aGUgeWVhci4gVGhlc2UgcGF0dGVybnMgaW4gdGhlIGV4cGVyaWVuY2VkIHRoZXJtYWwgZW52aXJvbm1lbnQgbWF5IGRyaXZlIHRoZSBvYnNlcnZlZCB2YXJpYXRpb24gaW4gY29wZXBvZCB0aGVybWFsIGxpbWl0cy4gSG93ZXZlciwgdGhlIHRpbWUgcGVyaW9kIGFmZmVjdGluZyBjb3BlcG9kIHRoZXJtYWwgbGltaXRzIGlzIHVua25vd24uIERlcGVuZGluZyB0aGUgb24gdGhlIGR1cmF0aW9uIG9mIHRpbWUgY29uc2lkZXJlZCwgdGhlcmUgYXJlIGxhcmdlIGNoYW5nZXMgaW4gdGhlIGV4cGVyaWVuY2VkIGVudmlyb25tZW50LCBpbiBwYXJ0aWN1bGFyIHJlZ2FyZGluZyB0aGUgdGVtcGVyYXR1cmUgcmFuZ2UgYW5kIHZhcmlhbmNlLiBDb25zaWRlciBmb3IgZXhhbXBsZSB0aHJlZSB0aW1lIHBlcmlvZHM6IHRoZSBkYXkgb2YgY29sbGVjdGlvbiwgb25lIHdlZWsgcHJpb3IgdG8gY29sbGVjdGlvbiwgYW5kIGZvdXIgd2Vla3MgcHJpb3IgdG8gY29sbGVjdGlvbi4gV2hpbGUgdGhlIG92ZXJhbGwgcGF0dGVybiBpcyBzaW1pbGFyLCB3ZSBjYW4gc2VlIHRoYXQsIHVuc3VycHJpc2luZ2x5LCBjb25zaWRlcmluZyBsb25nZXIgcGVyaW9kcyBvZiB0aW1lIHJlc3VsdHMgaW4gbGFyZ2VyIHJhbmdlcyBhbmQgc2xpZ2h0bHkgY2hhbmdlcyB0aGUgcGF0dGVybiBvZiB2YXJpYW5jZSBleHBlcmllbmNlZC4gCgpgYGB7ciBkYWlseS10ZW1wLWRhdGEsIGluY2x1ZGUgPSBGfQojIyBEYWlseSB2YWx1ZXMKZGFpbHlfdGVtcF9kYXRhID0gdGVtcF9kYXRhICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RlbXAgPSBtZWFuKHRlbXApLAogICAgICAgICAgICBtZWRfdGVtcCA9IG1lZGlhbih0ZW1wKSwKICAgICAgICAgICAgdmFyX3RlbXAgPSB2YXIodGVtcCksIAogICAgICAgICAgICBtaW5fdGVtcCA9IG1pbih0ZW1wKSwgCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXApKSAlPiUgCiAgbXV0YXRlKCJyYW5nZV90ZW1wIiA9IG1heF90ZW1wIC0gbWluX3RlbXApCgpkYXlfcHJpb3JfdGVtcF9kYXRhID0gdGVtcF9kYXRhICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZShkYXRlID0gZGF0ZSArIDEpICU+JSAKICByZW5hbWVfd2l0aCguZm4gPSB+IHBhc3RlMCgicHJpb3JfZGF5XyIsIC54KSwgLmNvbHMgPSBjKC1kYXRlKSkKCmRhaWx5X3Bsb3QgPSBkYWlseV90ZW1wX2RhdGEgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYygtZGF0ZSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdGVtcCwgY29sb3VyID0gcGFyYW1ldGVyKSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwgIAogICAgIm1pbl90ZW1wIiA9ICJkb2RnZXJibHVlIiwKICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiAgKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKICBnZ3RpdGxlKCJEYWlseSBWYWx1ZXMiKSArIAogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICB4ID0gIiIpICsgCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAoKYGBge3IgcHJlZGljdG9ycy1mdW5jdGlvbn0KIyMgRGVmaW5pbmcgdGhlIGZ1bmN0aW9uIHRvIGdldCBwcmVkaWN0b3IgdmFsdWVzIGZvciBwZXJpb2RzIG9mIGRpZmZlcmVudCBsZW5ndGhzCmdldF9wcmVkaWN0b3JzID0gZnVuY3Rpb24oZGFpbHlfdmFsdWVzLCByYXdfdGVtcCwgbl9kYXlzKXsKICBwcmVmaXggPSBzdHJfcmVwbGFjZV9hbGwoeGZ1bjo6bnVtYmVyc190b193b3JkcyhuX2RheXMpLCBwYXR0ZXJuID0gIiAiLCByZXBsYWNlbWVudCA9ICItIikKICAKICBtZWFuX3ZhbHVlcyA9IGRhaWx5X3ZhbHVlcyAlPiUgCiAgICB1bmdyb3VwKCkgJT4lIAogICAgbXV0YXRlKG1lYW5fbWF4ID0gc2xpZGVfdmVjKC54ID0gbWF4X3RlbXAsIC5mID0gbWVhbiwgLmJlZm9yZSA9IG5fZGF5cywgLmNvbXBsZXRlID0gVCksCiAgICAgICAgICAgbWVhbl9taW4gPSBzbGlkZV92ZWMoLnggPSBtaW5fdGVtcCwgLmYgPSBtZWFuLCAuYmVmb3JlID0gbl9kYXlzLCAuY29tcGxldGUgPSBUKSwKICAgICAgICAgICBtZWFuX3JhbmdlID0gc2xpZGVfdmVjKC54ID0gcmFuZ2VfdGVtcCwgLmYgPSBtZWFuLCAuYmVmb3JlID0gbl9kYXlzLCAuY29tcGxldGUgPSBUKSkgJT4lIAogICAgc2VsZWN0KGRhdGUsIG1lYW5fbWF4LCBtZWFuX21pbiwgbWVhbl9yYW5nZSkgJT4lIAogICAgcmVuYW1lX3dpdGgoIH4gcGFzdGUocHJlZml4LCAiZGF5IiwgLngsIHNlcCA9ICJfIiksIC5jb2xzID0gYygtZGF0ZSkpCiAgCiAgcGVyaW9kX3ZhbHVlcyA9IHJhd190ZW1wICU+JSAKICAgIG11dGF0ZShtZWFuID0gc2xpZGVfaW5kZXhfbWVhbih0ZW1wLCBpID0gZGF0ZSwgYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYV9ybSA9IFQpLAogICAgICAgICAgIG1heCA9IHNsaWRlX2luZGV4X21heCh0ZW1wLCBpID0gZGF0ZSwgYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtaW4gPSBzbGlkZV9pbmRleF9taW4odGVtcCwgaSA9IGRhdGUsIGJlZm9yZSA9IGRheXMobl9kYXlzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtZWQgPSBzbGlkZV9pbmRleF9kYmwodGVtcCwgLmkgPSBkYXRlLCAuYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBULCAuZiA9IG1lZGlhbiksCiAgICAgICAgICAgdmFyID0gc2xpZGVfaW5kZXhfZGJsKHRlbXAsIC5pID0gZGF0ZSwgLmJlZm9yZSA9IGRheXMobl9kYXlzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5mID0gdmFyKSwKICAgICAgICAgICByYW5nZSA9IG1heCAtIG1pbikgJT4lICAKICAgIHNlbGVjdCgtdGVtcCkgJT4lICAKICAgIGRpc3RpbmN0KCkgJT4lIAogICAgcmVuYW1lX3dpdGgoIH4gcGFzdGUocHJlZml4LCAiZGF5IiwgLngsIHNlcCA9ICJfIiksIC5jb2xzID0gYygtZGF0ZSkpJT4lIAogICAgaW5uZXJfam9pbihtZWFuX3ZhbHVlcywgYnkgPSBjKCJkYXRlIikpICU+JSAgCiAgICBkcm9wX25hKCkKICAKICByZXR1cm4ocGVyaW9kX3ZhbHVlcykKfQpgYGAKCmBgYHtyIG1pc2MtcHJlZGljdG9ycy1hbmQtcGxvdHMsIGZpZy53aWR0aD0xMiwgZmlnLmhlaWdodD01LCBpbmNsdWRlID0gRn0KIyAjIyBHZXR0aW5nIHByZWRpY3RvciB2YXJpYWJsZXMgZm9yIGRpZmZlcmVudCBwZXJpb2RzCiMgCiMgIyMjIFNob3J0ICh0aHJlZSBkYXlzKQojIHRocmVlX2RheV90ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X3RlbXAgPSB0ZW1wX2RhdGEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDMpCiMgCiMgIyMjIE9ORSBXRUVLCndlZWtfdGVtcHMgPSBnZXRfcHJlZGljdG9ycyhkYWlseV92YWx1ZXMgPSBkYWlseV90ZW1wX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDcpCgp3ZWVrX3Bsb3QgPSB3ZWVrX3RlbXBzICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygtZGF0ZSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoInNldmVuX2RheV9tZWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X21lZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9tYXgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJzZXZlbl9kYXlfbWluIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9yYW5nZSIpKSAlPiUKICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKICAgICJtZWFuX3RlbXAiID0gIm9saXZlZHJhYjMiLAogICAgIm1lZF90ZW1wIiA9ICJzZWFncmVlbjMiLAogICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLAogICAgIm1pbl90ZW1wIiA9ICJkb2RnZXJibHVlIiwKICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiAgKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBhcy5EYXRlKGMoIjIwMjMtMDEtMDEiLCAiMjAyMy0wNC0wMSIsICIyMDIzLTA3LTAxIikpKSArCiAgZ2d0aXRsZSgiT25lIFdlZWsiKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIFRXTyBXRUVLUwojIHR3b193ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDE0KQojIAojIHR3b193ZWVrX3Bsb3QgPSB0d29fd2Vla190ZW1wcyAlPiUgCiMgICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAojICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAojICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lIAojICAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoImZvdXJ0ZWVuX2RheV9tZWFuIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfbWVkIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfbWF4IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm91cnRlZW5fZGF5X21pbiIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV92YXIiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV9yYW5nZSIpKSAlPiUgCiMgICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKIyAgICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiMgICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKIyAgICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLCAgCiMgICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiMgICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKIyAgICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKIyAgICkpICsgCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKIyAgIGdndGl0bGUoIlR3byBXZWVrcyIpICsgCiMgICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAojICAgICAgICB4ID0gIiIpICsgCiMgICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKyAKIyAgIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIEZPVVIgV0VFS1MKZm91cl93ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gMjgpCgpmb3VyX3dlZWtfcGxvdCA9IGZvdXJfd2Vla190ZW1wcyAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgJWluJSBjKCJ0d2VudHktZWlnaHRfZGF5X21lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X21lZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfbWF4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAidHdlbnR5LWVpZ2h0X2RheV9taW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfcmFuZ2UiKSkgJT4lCiAgbXV0YXRlKHBhcmFtZXRlciA9IHBhc3RlKHdvcmQocGFyYW1ldGVyLCBzdGFydCA9IDMsIHNlcCA9IGZpeGVkKCJfIikpLCAiX3RlbXAiLCBzZXAgPSAiIikpICU+JQogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wLCBjb2xvdXIgPSBwYXJhbWV0ZXIpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwKICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiAgICAidmFyX3RlbXAiID0gImRhcmtnb2xkZW5yb2QxIgogICkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKwogIGdndGl0bGUoIkZvdXIgV2Vla3MiKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIEVJR0hUIFdFRUtTCiMgZWlnaHRfd2Vla190ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gNTYpCiMgCiMgZWlnaHRfd2Vla19wbG90ID0gZWlnaHRfd2Vla190ZW1wcyAlPiUgCiMgICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAojICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAojICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lIAojICAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoImZpZnR5LXNpeF9kYXlfbWVhbiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9tZWQiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZpZnR5LXNpeF9kYXlfbWF4IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9taW4iLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmaWZ0eS1zaXhfZGF5X3ZhciIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9yYW5nZSIpKSAlPiUgCiMgICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKIyAgICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiMgICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKIyAgICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLCAgCiMgICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiMgICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKIyAgICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKIyAgICkpICsgCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKIyAgIGdndGl0bGUoIkVpZ2h0IFdlZWtzIikgKyAKIyAgIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiMgICAgICAgIHggPSAiIikgKyAKIyAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKIyAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKIyAKZ2dhcnJhbmdlKGRhaWx5X3Bsb3QsIHdlZWtfcGxvdCwgZm91cl93ZWVrX3Bsb3QsIAogICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFQsIG5yb3cgPSAxLCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpgYGB7ciBtaXNjLWNvcnItcGVyaW9kcywgaW5jbHVkZSA9IEZ9CiNUaGUgZGlmZmVyZW50IHRpbWUgcGVyaW9kcyBleGFtaW5lZCBieSB0aGlzIGNsaW1hdGUgZGF0YSBoaWdobGlnaHRzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGNoYW5nZXMgYmFzZWQgb24gdGhlIHdpbmRvdyBleGFtaW5lZC4gRm9yIGV4YW1wbGUsIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGV4cGVyaWVuY2VkIG92ZXIgd2Vla2x5IGludGVydmFscyBhcmUgY2xvc2VseSBsaW5rZWQsIHdoZXJlYXMgdGhlcmUgaXMgYSBkaXN0aW5jdCBzZWFzb25hbCBjeWNsZSBpbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWluaW11bSBhbmQgbWF4aW11bSB0ZW1wZXJhdHVyZXMgZXhwZXJpZW5jZWQgb3ZlciBwZXJpb2RzIG9mIGZvdXIgd2Vla3MuIAoKb25lX3dlZWtfZG95X2RhdGEgPSB3ZWVrX3RlbXBzICU+JSAKICBtdXRhdGUoZG95ID0geWRheShkYXRlKSkKCm9uZV93ZWVrX3RlbXBfY2lyY2xlID0gZ2dwbG90KG9uZV93ZWVrX2RveV9kYXRhLCBhZXMoeCA9IHNldmVuX2RheV9tZWFuX21heCwgeSA9IHNldmVuX2RheV9tZWFuX21pbiwgY29sb3VyID0gZG95KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKAogICAgaGlnaCA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWQgPSAiY29yYWwyIiwKICAgIGxvdyA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWRwb2ludCA9IDE4Mi41KSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgbGFicyh4ID0gIk1heC4gVGVtcC4gKMKwQykiLAogICAgICAgeSA9ICJNaW4uIFRlbXAuICjCsEMpIikgKyAKICBnZ3RpdGxlKCJPbmUgV2VlayIpICsgCiAgdGhlbWVfbWF0dCgpCgpmb3VyX3dlZWtfZG95X2RhdGEgPSBmb3VyX3dlZWtfdGVtcHMgJT4lIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpKQoKZm91cl93ZWVrX3RlbXBfY2lyY2xlID0gZ2dwbG90KGZvdXJfd2Vla19kb3lfZGF0YSwgYWVzKHggPSBgdHdlbnR5LWVpZ2h0X2RheV9tYXhgLCB5ID0gYHR3ZW50eS1laWdodF9kYXlfbWluYCwgY29sb3VyID0gZG95KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKAogICAgaGlnaCA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWQgPSAiY29yYWwyIiwKICAgIGxvdyA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWRwb2ludCA9IDE4Mi41KSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgZ2d0aXRsZSgiRm91ciBXZWVrIikgKyAKICB0aGVtZV9tYXR0KCkKCmdnYXJyYW5nZShvbmVfd2Vla190ZW1wX2NpcmNsZSwgZm91cl93ZWVrX3RlbXBfY2lyY2xlLAogICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJib3R0b20iKQpgYGAKCk9yZ2FuaXNtcyBhcmUgdW5saWtlbHkgdG8gYWNjbGltYXRlIGluc3RhbnRhbmVvdXNseSB0byBjaGFuZ2VzIGluIHRlbXBlcmF0dXJlLiBUbyBleHBsb3JlIHRoZSBwb3RlbnRpYWwgdGVtcG9yYWwgd2luZG93IHRoZXNlIGNvcGVwb2RzIGFyZSByZXNwb25kaW5nIHRvLCB3ZSBleGFtaW5lZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVybWFsIGxpbWl0cyBhbmQgc3VtbWFyaWVzIG9mIHRoZSB0aGVybWFsIGVudmlyb25tZW50IG92ZXIgZGlmZmVyZW50IHBlcmlvZHMgb2YgdGltZS4gRm9yIGVhY2ggc3BlY2llcyAoaW5jbHVzaXZlIG9mIGFsbCBzZXhlcyBhbmQgc3RhZ2VzKSwgd2UgZXhhbWluZWQgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gQ1RtYXggYW5kIG9uZSBvZiBuaW5lIHJlcHJlc2VudGF0aW9ucyBvZiB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudCBjYWxjdWxhdGVkIGZvciBwZXJpb2RzIG9mIHRpbWUgZnJvbSAxIHRvIDYwIGRheXMgYmVmb3JlIGNvbGxlY3Rpb24uIFRoZXNlIHBhcmFtZXRlcnMgaW5jbHVkZSB0aGUgb3ZlcmFsbCBtYXhpbXVtLCBtaW5pbXVtLCBtZWRpYW4sIGFuZCBtZWFuIHRlbXBlcmF0dXJlIGZvciB0aGUgcGVyaW9kIG9mIHRpbWUsIHRoZSB0ZW1wZXJhdHVyZSByYW5nZSBhbmQgdmFyaWFuY2UgZHVyaW5nIHRoaXMgdGltZSwgYW5kIHRoZSBtZWFuIGRhaWx5IHRlbXBlcmF0dXJlIG1heGltdW0sIG1pbmltdW0sIGFuZCByYW5nZS4gV2UgYWxzbyBleGFtaW5lZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiBDVG1heCBhbmQgdGhlIHRlbXBlcmF0dXJlIHJlY29yZGVkIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24uIAoKYGBge3IgZXN0aW1hdGluZy1wcmVkaWN0b3ItY29ycmVsYXRpb25zLCBpbmNsdWRlID0gRn0KI1dlIGNhbiBzZWUgdGhhdCwgaW4gZ2VuZXJhbCwgY29wZXBvZHMgYXJlIHJlc3BvbmRpbmcgdG8gcHJveGltYXRlIGN1ZXMgZnJvbSB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudCwgd2l0aCBjb3JyZWxhdGlvbnMgZ2VuZXJhbGx5IGRyb3BwaW5nIG9mZiBzdWJzdGFudGlhbGx5IGFzIGFjY2xpbWF0aW9uIHdpbmRvdyBkdXJhdGlvbiBpbmNyZWFzZXMuIEFuIGV4Y2VwdGlvbiBpcyAqRXBpc2NodXJhIGxhY3VzdHJpcyosIHdoaWNoIGFwcGVhcnMgdG8gYmUgcmVzcG9uZGluZyB0byBtYXhpbXVtIHRlbXBlcmF0dXJlcyBleHBlcmllbmNlZCBvdmVyIGEgMjAgZGF5IHRpbWUgcGVyaW9kLiAKCiMjIyBQdWxsaW5nIHByZWRpY3RvcnMgYW5kIG1lYXN1cmluZyBjb3JyZWxhdGlvbnMgZm9yIG11Y2ggZmluZXIgdGltZXNjYWxlczsgMS01NiBkYXlzCgpudW1fY29sbHMgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBzcF9uYW1lKSAlPiUgIAogIGRpc3RpbmN0KCkgJT4lICAKICBjb3VudChzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKG4gPj0gNSkKCmNvcnJfdmFscyA9IGRhdGEuZnJhbWUoKQoKZHVyX3ZhbHMgPSBjKDE6NTApCmZvcihpIGluIGR1cl92YWxzKXsKICAKICBkdXJhdGlvbl90ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHNlbGVjdCh0ZW1wX2RhdGEsIC1ob3VyKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSBpKSAlPiUgCiAgICBmaWx0ZXIoZGF0ZSAlaW4lIGFzX2RhdGUodW5pcXVlKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX2RhdGUpKSkKICAKICBjb3JyX2RhdGEgPSBmdWxsX2RhdGEgJT4lCiAgICBzZWxlY3Qoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlLCBjb2xsZWN0aW9uX3RlbXAsIHNleCwgY3RtYXgpICU+JSAKICAgIGZpbHRlcihzcF9uYW1lICVpbiUgbnVtX2NvbGxzJHNwX25hbWUpICU+JSAKICAgICNmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgICBtdXRhdGUoY29sbGVjdGlvbl9kYXRlID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgICBpbm5lcl9qb2luKGR1cmF0aW9uX3RlbXBzLCBqb2luX2J5KGNvbGxlY3Rpb25fZGF0ZSA9PSBkYXRlKSkgJT4lIAogICAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKGNvbGxlY3Rpb25fdGVtcCwgY29udGFpbnMoImRheV8iKSksCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIiwgCiAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAicHJlZGljdG9yIikgJT4lICAKICAgIGdyb3VwX2J5KHNwX25hbWUsIHByZWRpY3RvcikgJT4lIAogICAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRlc3RpbWF0ZSwKICAgICAgICAgICAgICBwLnZhbHVlID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRwLnZhbHVlLAogICAgICAgICAgICAgIGNpX2xvdyA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMV0sCiAgICAgICAgICAgICAgY2lfaGlnaCA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMl0sCiAgICAgICAgICAgICAgLmdyb3VwcyA9ICJrZWVwIikgJT4lIAogICAgZmlsdGVyKHByZWRpY3RvciAhPSAiY29sbGVjdGlvbl90ZW1wIikgJT4lIAogICAgbXV0YXRlKHNpZyA9IGlmZWxzZShwLnZhbHVlIDwwLjA1LCAiU2lnLiIsICJOb24gU2lnLiIpKSAlPiUgCiAgICBzZXBhcmF0ZShwcmVkaWN0b3IsICJfZGF5XyIsIGludG8gPSBjKE5BLCAicGFyYW1ldGVyIikpICU+JSAKICAgIG11dGF0ZShkdXJhdGlvbiA9IGkpCiAgCiAgY29ycl92YWxzID0gYmluZF9yb3dzKGNvcnJfdmFscywgY29ycl9kYXRhKQp9Cgpjb2xsX2NvcnIgPSBmdWxsX2RhdGEgJT4lCiAgZmlsdGVyKHNwX25hbWUgJWluJSBudW1fY29sbHMkc3BfbmFtZSkgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yLnRlc3QoY3RtYXgsIGNvbGxlY3Rpb25fdGVtcCkkZXN0aW1hdGUsCiAgICAgICAgICAgIHAudmFsdWUgPSBjb3IudGVzdChjdG1heCwgY29sbGVjdGlvbl90ZW1wKSRwLnZhbHVlLAogICAgICAgICAgICBjaV9sb3cgPSBjb3IudGVzdChjdG1heCwgY29sbGVjdGlvbl90ZW1wKSRjb25mLmludFsxXSwKICAgICAgICAgICAgY2lfaGlnaCA9IGNvci50ZXN0KGN0bWF4LCBjb2xsZWN0aW9uX3RlbXApJGNvbmYuaW50WzJdKSAlPiUgCiAgbXV0YXRlKHNpZyA9IGlmZWxzZShwLnZhbHVlIDwwLjA1LCAiU2lnLiIsICJOb24gU2lnLiIpKSAlPiUgCiAgbXV0YXRlKGR1cmF0aW9uID0gMCwKICAgICAgICAgcGFyYW1ldGVyID0gImNvbGxfdGVtcCIpCgpjb3JyX3ZhbHMgPSBjb3JyX3ZhbHMgJT4lICAKICBtdXRhdGUoZHVyYXRpb24gPSBhcy5udW1lcmljKGR1cmF0aW9uKSkgJT4lIAogIGJpbmRfcm93cyhjb2xsX2NvcnIpCgpgYGAKClNob3duIGJlbG93IGFyZSB0aGUgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGZvciB0aGVzZSByZWxhdGlvbnNoaXBzLiBFYWNoIGZhY2V0IHNob3dzIHRoZSByZWxhdGlvbnNoaXAgZm9yIGEgZGlmZmVyZW50IHBhcmFtZXRlciwgcGxvdHRlZCBhZ2FpbnN0IHRoZSBkdXJhdGlvbiBvZiB0aGUgdGltZSBwZXJpb2QgYmVmb3JlIGNvbGxlY3Rpb24uIAoKYGBge3Igc3VwcC1maWctY29ycmVsYXRpb24tZHVyYXRpb25zLCBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9OCwgaW5jbHVkZSA9IFR9CmNvcnJfdmFscyAlPiUgCiAgbXV0YXRlKHBhcmFtZXRlciA9IGZjdF9yZWxldmVsKHBhcmFtZXRlciwgYygibWluIiwgIm1heCIsICJyYW5nZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbiIsICJtZWQiLCAidmFyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtZWFuX21pbiIsICJtZWFuX21heCIsICJtZWFuX3JhbmdlIikpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZHVyYXRpb24sIHkgPSBjb3JyZWxhdGlvbiwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcCgufnBhcmFtZXRlcikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDAuOSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMS41KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJEdXJhdGlvbiAoZGF5cykiLAogICAgICAgeSA9ICJDb3JyZWxhdGlvbiIsIAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkKYGBgCgpUaGlzIHRhYmxlIGNvbnRhaW5zIHRoZSB0b3AgdGhyZWUgZmFjdG9ycyBmb3IgZWFjaCBzcGVjaWVzIChiYXNlZCBvbiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCkuCgpgYGB7ciBwcmVkaWN0b3ItY29ycmVsYXRpb25zLCBpbmNsdWRlID0gRn0KY29ycl92YWxzICU+JSAgCiAgZmlsdGVyKHNpZyA9PSAiU2lnLiIpICU+JSAKICBkcm9wX25hKGNvcnJlbGF0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lCiAgYXJyYW5nZShkZXNjKGNvcnJlbGF0aW9uKSkgJT4lIAogIHNsaWNlX2hlYWQobiA9IDMpICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIlByZWRpY3RvciIgPSBwYXJhbWV0ZXIsICJEdXJhdGlvbiIgPSBkdXJhdGlvbiwgIkNvcnJlbGF0aW9uIiA9IGNvcnJlbGF0aW9uLCAiUC1WYWx1ZSIgPSBwLnZhbHVlKSAlPiUgCiAga25pdHI6OmthYmxlKGFsaWduID0gImMiKQpgYGAKClNob3duIGhlcmUgaXMgYSBncmFwaGljYWwgc3VtbWFyeSBvZiB0aGUgZHVyYXRpb24gb2YgdGhlIGJlc3QgcHJlZGljdG9ycyBmb3IgZWFjaCBzcGVjaWVzLiBOb3RlIHRoYXQgZm9yIHRoZSB0d28gTGVwdG9kaWFwdG9taWRzLCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIGhhZCB0aGUgbGFyZ2VzdCBjb3JyZWxhdGlvbiBjb2VmZmljaWVudCBzbyBkdXJhdGlvbiBpcyB6ZXJvLiBUaGlzIHJlcHJlc2VudGF0aW9uIGhpZ2hsaWdodHMgdGhhdCB0aGVyZSBpcyB2YXJpYXRpb24gYWNyb3NzIHRoZSBjb21tdW5pdHkgbm90IG9ubHkgaW4gdGhlIHBvdGVudGlhbCBkcml2ZXIgKGUuZy4gbWluaW11bSB2cy4gbWF4aW11bSB0ZW1wZXJhdHVyZXMpIGJ1dCBhbHNvIGluIHRoZSBkdXJhdGlvbiBvZiB0aW1lLiBUaGlzIHZhcmlhdGlvbiBpcyBub3QgZ3JvdXBlZCBieSBzZWFzb24gKHRoZSB3aW50ZXIgYW5kIHN1bW1lciBjb21tdW5pdGllcyBib3RoIGhhdmUgcmVwcmVzZW50YXRpdmUgc3BlY2llcyBhcHBhcmVudGx5IHJlc3BvbmRpbmcgdG8gc2hvcnQgYW5kIGxvbmcgZHVyYXRpb25zKS4gCgpgYGB7ciBtYWluLWZpZy1hY2MtZHVyYXRpb25zfQpkdXJhdGlvbl9wbG90ID0gY29ycl92YWxzICU+JSAgCiAgZmlsdGVyKHNpZyA9PSAiU2lnLiIpICU+JSAKICBkcm9wX25hKGNvcnJlbGF0aW9uKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lCiAgYXJyYW5nZShkZXNjKGNvcnJlbGF0aW9uKSkgJT4lIAogIHNsaWNlX2hlYWQobiA9IDEpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZSgibnVtIiA9IHJvd19udW1iZXIoKSwgCiAgICAgICAgIHNwX25hbWUgPSBmY3RfcmVvcmRlcihzcF9uYW1lLCBkdXJhdGlvbiwgLmZ1biA9IG1lYW4sIC5kZXNjID0gVCkpICU+JSAKICBhcnJhbmdlKHNwX25hbWUpICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIlByZWRpY3RvciIgPSBwYXJhbWV0ZXIsICJEdXJhdGlvbiIgPSBkdXJhdGlvbiwgIkNvcnJlbGF0aW9uIiA9IGNvcnJlbGF0aW9uLCBudW0pICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBTcGVjaWVzLCB5ID0gRHVyYXRpb24sIGZpbGwgPSBQcmVkaWN0b3IsIGdyb3VwID0gbnVtKSkgKyAKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAwLjUsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjYpLAogICAgICAgICAgIGNvbG91ciA9ICJibGFjayIpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiY29sbF90ZW1wIiA9ICJibGFjayIsICJtYXgiID0gIndoaXRlIiwgIm1pbiIgPSAiZ3JleSIpKSArIAogIGxhYnMoeCA9ICIiLCAKICAgICAgIHkgPSAiRHVyYXRpb24gXG4oZGF5cykiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCmBgYHtyIG1haW4tZmlnLWFjYy1jb3JyZWxhdGlvbnMsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTZ9CmNvcnJlbGF0aW9uX2NvZWZfcGxvdCA9IGNvcnJfdmFscyAlPiUgIAogIGZpbHRlcihzaWcgPT0gIlNpZy4iIHwgcGFyYW1ldGVyID09ICJjb2xsX3RlbXAiKSAlPiUgCiAgZHJvcF9uYShjb3JyZWxhdGlvbikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgPT0gImNvbGxfdGVtcCIgfCBjb3JyZWxhdGlvbiA9PSBtYXgoY29ycmVsYXRpb24pKSAlPiUgCiAgYXJyYW5nZShzcF9uYW1lLCBwYXJhbWV0ZXIpICU+JSAKICBtdXRhdGUoIm51bSIgPSByb3dfbnVtYmVyKCkpICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIlByZWRpY3RvciIgPSBwYXJhbWV0ZXIsICJEdXJhdGlvbiIgPSBkdXJhdGlvbiwgIkNvcnJlbGF0aW9uIiA9IGNvcnJlbGF0aW9uLCBudW0pICU+JSAKICBtdXRhdGUoUHJlZGljdG9yID0gaWZfZWxzZShQcmVkaWN0b3IgPT0gImNvbGxfdGVtcCIsIFByZWRpY3RvciwgImJlc3QiKSkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgbXV0YXRlKFNwZWNpZXMgPSBmY3RfcmVvcmRlcihTcGVjaWVzLCBEdXJhdGlvbiwgLmZ1biA9IG1heCwgLmRlc2MgPSBUKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFNwZWNpZXMsIHkgPSBDb3JyZWxhdGlvbiwgZmlsbCA9IFByZWRpY3RvciwgZ3JvdXAgPSBudW0pKSArIAogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCB3aWR0aCA9IDAuNSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNiksCiAgICAgICAgICAgY29sb3VyID0gImJsYWNrIikgKyAKICBsYWJzKHkgPSAiQ29ycmVsYXRpb24gXG5Db2VmZmljaWVudCIsCiAgICAgICBmaWxsID0gIkNvcnJlbGF0ZSIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJjb2xsX3RlbXAiID0gImJsYWNrIiwgImJlc3QiID0gIndoaXRlIikpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMSksIGxpbWl0cyA9IGMoMCwxKSkgKwogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKCmdnYXJyYW5nZShkdXJhdGlvbl9wbG90LCBjb3JyZWxhdGlvbl9jb2VmX3Bsb3QsIG5yb3cgPSAyLCBsZWdlbmQgPSAicmlnaHQiLCAKICAgICAgICAgIGhlaWdodHMgPSBjKDAuNCwgMC42KSkKYGBgCgpgYGB7ciBtaXNjLWFjYy1kdXJhdGlvbi1wbG90LCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD00LCBpbmNsdWRlID0gRn0KIyBQaGVub3R5cGljIHZhcmlhdGlvbiAobGlrZSBhY2NsaW1hdGlvbiBvZiB0aGVybWFsIGxpbWl0cykgaXMgYSBwaHlzaW9sb2dpY2FsIHByb2Nlc3MuIGRlcGVuZGluZyBvbiB0aGUgbWVjaGFuaXN0aWMgdW5kZXJwaW5uaW5ncyAoY2hhbmdlcyBpbiBIU1AgZXhwcmVzc2lvbiwgZXRjLiksIHRoZSBhbW91bnQgb2YgdGltZSBpdCB0YWtlcyBmb3IgYW4gaW5kaXZpZHVhbCB0byBhY2NsaW1hdGUgbWF5IHZhcnkgYmFzZWQgb24gYm9keSBzaXplIChsYXJnZXIgc3BlY2llcywgbW9yZSBjZWxscywgbW9yZSB0aW1lIHJlcXVpcmVkIHRvIGFjY2xpbWF0ZSkuIFNob3duIGhlcmUgaXMgdGhlIGR1cmF0aW9uIG9mIHRoZSBlbnZpcm9ubWVudGFsIGFjY2xpbWF0aW9uIHdpbmRvdyB0aGUgY29wZXBvZHMgYXBwZWFyIHRvIGJlIHJlc3BvbmRpbmcgdG8uICAKCm1lYW5fc2l6ZXMgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgIAogIHN1bW1hcmlzZShtZWFuX3NpemUgPSBtZWFuKHNpemUsIG5hLnJtID0gVCkpCgpjb3JyX3ZhbHMgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSAKICBmaWx0ZXIoY29ycmVsYXRpb24gPT0gbWF4KGNvcnJlbGF0aW9uKSkgJT4lICAKICBpbm5lcl9qb2luKG1lYW5fc2l6ZXMsIGJ5ID0gInNwX25hbWUiKSAlPiUgCiAgc2VsZWN0KHNwX25hbWUsIGR1cmF0aW9uLCBtZWFuX3NpemUpICU+JSAgCiAgZ2dwbG90KGFlcyh4ID0gbWVhbl9zaXplLCB5ID0gZHVyYXRpb24pKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNwX25hbWUpLCAKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJNZWFuIEZlbWFsZSBTaXplIChtbSkiLAogICAgICAgeSA9ICJBY2NsaW1hdGlvbiBEdXJhdGlvbiIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgojIyBUcmFpdCBWYXJpYXRpb24gCgpTaG93biBiZWxvdyBhcmUgdGhlIGNsdXRjaCBzaXplIGRpc3RyaWJ1dGlvbnMgZm9yIHRoZSB0aHJlZSBkaWFwdG9taWlkIHNwZWNpZXMsIHdoaWNoIHByb2R1Y2UgZWdnIHNhY3MgdGhhdCBhbGxvdyBmb3IgZWFzeSBxdWFudGlmaWNhdGlvbiBvZiBmZWN1bmRpdHkuIAoKYGBge3Igc3VwcC1maWctZmVjdW5kaXR5LWhpc3RvZ3JhbSwgZmlnLndpZHRoPTcsIGZpZy5oZWlnaHQ9MTB9CmZ1bGxfZGF0YSAlPiUgIAogIGRyb3BfbmEoZmVjdW5kaXR5KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGZlY3VuZGl0eSwgZmlsbCA9IHNwX25hbWVfc3ViKSkgKyAKICBmYWNldF93cmFwKC5+c3BfbmFtZV9zdWIsIG5jb2wgPSAxKSArIAogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMikgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkZlY3VuZGl0eSAoIyBFZ2dzKSIpICsKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCk9uZSBvZiB0aGUgbWFpbiBhaW1zIG9mIHRoaXMgcHJvamVjdCBpcyB0byBleGFtaW5lIHRoZSBwYXR0ZXJucyBhbmQgcHJvY2Vzc2VzIGRyaXZpbmcgdmFyaWF0aW9uIGluIHVwcGVyIHRoZXJtYWwgbGltaXRzIGFjcm9zcyB0aGVzZSBzcGVjaWVzIG9mIGNvcGVwb2RzLiAKCiMjIyBWYXJpYXRpb24gd2l0aCB0ZW1wZXJhdHVyZSAKCldlIGV4cGVjdCBvbmUgb2YgdGhlIHByaW1hcnkgZHJpdmVycyBvZiBjb3BlcG9kIHRoZXJtYWwgbGltaXRzIHRvIGJlIHRlbXBlcmF0dXJlLCBhcyBpbmRpdmlkdWFscyBhY2NsaW1hdGUgdG8gc2Vhc29uYWwgY2hhbmdlcy4gU2hvd24gYmVsb3cgYXJlIHRoZSBzZWFzb25hbCBwYXR0ZXJucyBvZiB3aGVuIGNvcGVwb2RzIHdlcmUgaW5jbHVkZWQgaW4gQ1RtYXggbWVhc3VyZW1lbnRzIChhIHByb3h5IGZvciB0aGUgc2Vhc29uIG9mIG9jY3VycmVuY2UpLCBhbmQgdGhlcm1hbCBsaW1pdHMgZm9yIGVhY2ggc3BlY2llcyBwbG90dGVkIGFnYWluc3QgdGhlIHRlbXBlcmF0dXJlIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24uIFdlIGdlbmVyYWxseSBzZWUgYW4gaW5jcmVhc2UgaW4gdGhlcm1hbCBsaW1pdHMgd2l0aCBpbmNyZWFzaW5nIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUuCgpgYGB7ciBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpzcF9jdG1heF90ZW1wID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc3BfbmFtZSAhPSAiT3NwaHJhbnRpY3VtIGxhYnJvbmVjdHVtIikgJT4lIAogIG11dGF0ZShzcF9uYW1lID0gYXMuZmFjdG9yKHNwX25hbWUpLAogICAgICAgICBzcF9uYW1lID0gZmN0X3Jlb3JkZXIoc3BfbmFtZSwgY3RtYXgsIC5kZXNjID0gVCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAxLjUsIGNvbG91ciA9ICJncmV5MzAiKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC40KSArIAogIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKYGBge3IgbWFpbi1maWctc3Atc3VtbWFyaWVzLCBmaWcud2lkdGg9MTQsIGZpZy5oZWlnaHQ9NX0KZ2dhcnJhbmdlKHNhbXBsZV9kYXRlc19wbG90LCBzcF9jdG1heF90ZW1wLCBucm93ID0gMSwgCiAgICAgICAgICBsYWJlbHMgPSAiQVVUTyIpCmBgYAoKVGhlIGludGVyYWN0aW9uIGJldHdlZW4gc2Vhc29uYWwgY2hhbmdlcyBpbiB0ZW1wZXJhdHVyZSBhbmQgdGhlIGFjY2xpbWF0aW9uIG9mIHRoZXJtYWwgbGltaXRzIGxpa2VseSBhZmZlY3RzIHZ1bG5lcmFiaWxpdHkgb2YgZWFjaCBzcGVjaWVzIHRvIHdhcm1pbmcuIFNob3duIGJlbG93IGFyZSB3YXJtaW5nIHRvbGVyYW5jZSB2YWx1ZXMgZm9yIGVhY2ggc3BlY2llcywgY2FsY3VsYXRlZCBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGluZGl2aWR1YWwgQ1RtYXggYW5kIHRoZSB0ZW1wZXJhdHVyZSBhdCB0aGUgdGltZSBvZiBjb2xsZWN0aW9uLiBBbGwgc3BlY2llcyBtYWludGFpbmVkIHNvbWUgZGVncmVlIG9mIGJ1ZmZlciBiZXR3ZWVuIGVudmlyb25tZW50YWwgdGVtcGVyYXR1cmVzIGFuZCB1cHBlciB0aGVybWFsIGxpbWl0cywgYnV0ICpMLiBtaW51dHVzKiBhcHBlYXJzIHRvIGFwcHJvYWNoIGl0cyB1cHBlciB0aGVybWFsIGxpbWl0IGR1cmluZyB0aGUgd2FybWVzdCBjb2xsZWN0aW9ucyBkdXJpbmcgdGhlIHN1bW1lci4gCgpBbHNvIHNob3duIGJlbG93IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBmZWN1bmRpdHkgKHRoZSBudW1iZXIgb2YgZWdncyBjb250YWluZWQgaW4gYSBjbHV0Y2gpIGZvciB0aGUgdGhyZWUgZGlhcHRvbWlkIHNwZWNpZXMuIEZvciB0aGUgdHdvIExlcHRvZGlhcHRvbXVzIHNwZWNpZXMsIHRoZXJlIGlzIG5vIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGNsdXRjaCBzaXplIGFuZCB0ZW1wZXJhdHVyZSwgd2hpbGUgdGhlcmUgYXBwZWFycyB0byBiZSBhIGdlbmVyYWwgaW5jcmVhc2UgaW4gY2x1dGNoIHNpemUgd2l0aCB0ZW1wZXJhdHVyZSBpbiB0aGUgU2tpc3RvZGlhcHRvbXVzIHNwZWNpZXMuIAoKYGBge3IgbWFpbi1maWctdHJhaXQtY29sbC10ZW1wLXBsb3RzLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9N30KCnd0X3RlbXAgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzcF9uYW1lICE9ICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gd2FybWluZ190b2wsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsaW5ld2lkdGggPSAzKSArCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIHkgPSAiV2FybWluZyBUb2xlcmFuY2UgKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSAgKyAKICB5bGltKDAsMzApICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQoKZWdnc190ZW1wID0gZnVsbF9kYXRhICU+JSAKICBmaWx0ZXIoc3BfbmFtZSAhPSAiT3NwaHJhbnRpY3VtIGxhYnJvbmVjdHVtIikgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGZlY3VuZGl0eSwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIGFscGhhID0gMC4zKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxpbmV3aWR0aCA9IDMpICsKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wZXJhdHVyZSAowrBDKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSAgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKZ2dhcnJhbmdlKHd0X3RlbXAsIGVnZ3NfdGVtcCwgCiAgICAgICAgICBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgpgYGB7ciBzdXBwLWZpZy1sc2ljLW1vcnBocywgaW5jbHVkZSA9IEZ9Cm1vcnBoX2RhdGEgPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIgJiBzcGVjaWVzID09ICJsZXB0b2RpYXB0b211c19zaWNpbGlzIikgJT4lICBtdXRhdGUoc3BfbmFtZSA9IGNhc2Vfd2hlbigKICAgIHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiICYgc2l6ZSA+PSAwLjg5IH4gIkxhcmdlIiwKICAgIHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiICYgc2l6ZSA8IDAuODkgfiAiU21hbGwiLAogICAgLmRlZmF1bHQgPSBzcF9uYW1lCiAgKSkKCmdncGxvdChtb3JwaF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuOCkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGxpbmV3aWR0aCA9IDIpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciBtaXNjLWN0bWF4LXJhbmdlLXBsb3QsIGluY2x1ZGUgPSBGfQpmdWxsX2RhdGEgJT4lICAKICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlLCBjb2xsZWN0aW9uX3RlbXApICU+JSAgCiAgc3VtbWFyaXNlKCJjdG1heF9yYW5nZSIgPSBtYXgoY3RtYXgpIC0gbWluKGN0bWF4KSwKICAgICAgICAgICAgImN0bWF4X3ZhciIgPSB2YXIoY3RtYXgpLAogICAgICAgICAgICAic2FtcGxlX3NpemUiID0gbigpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgIT0gIkxlcHRvZG9yYSBraW5kdGkiKSAlPiUgCiAgZmlsdGVyKHNhbXBsZV9zaXplID4gMykgJT4lIAogIGdncGxvdChhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGN0bWF4X3ZhciwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3VyID0gImJsYWNrIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKYGBge3IgY3RtYXgtY29sbC10ZW1wLW1vZGVsLCBpbmNsdWRlID0gRn0KIyBhZHVsdF9kYXRhID0gZnVsbF9kYXRhICU+JSAKIyAgIGZpbHRlcihzZXggPT0gImZlbWFsZSIpCgojIAojIGN0bWF4X3RlbXAubW9kZWwgPSBsbShkYXRhID0gbW9kZWxfZGF0YSwgY3RtYXggfiB0ZW1wX2NlbnQgKiBzcF9uYW1lKQojIHNpemVfdGVtcC5tb2RlbCA9IGxtKGRhdGEgPSBtb2RlbF9kYXRhLCBzaXplIH4gdGVtcF9jZW50ICogc3BfbmFtZSkKIyBmZWN1bmRfdGVtcC5tb2RlbCA9IGxtKGRhdGEgPSBkcm9wX25hKG1vZGVsX2RhdGEsIGZlY3VuZGl0eSksIGZlY3VuZGl0eSB+IHRlbXBfY2VudCAqIHNwX25hbWUpCiMgCiMgZmVjdW5kaXR5X3Jlc2lkcyA9IGNiaW5kKGRyb3BfbmEobW9kZWxfZGF0YSwgZmVjdW5kaXR5KSwgImZlY3VuZGl0eV9yZXNpZHMiID0gZmVjdW5kX3RlbXAubW9kZWwkcmVzaWR1YWxzKSAlPiUgCiMgICBzZWxlY3QoY29sbGVjdGlvbl9kYXRlLCBleHBfZGF0ZSwgcmVwbGljYXRlLCBzcGVjaWVzLCB0dWJlLCBmZWN1bmRpdHlfcmVzaWRzKQojIAojIGN0bWF4X3Jlc2lkcyA9IGNiaW5kKG1vZGVsX2RhdGEsICJyZXNpZHMiID0gY3RtYXhfdGVtcC5tb2RlbCRyZXNpZHVhbHMsICJzaXplX3Jlc2lkcyIgPSBzaXplX3RlbXAubW9kZWwkcmVzaWR1YWxzKSAlPiUgCiMgICBsZWZ0X2pvaW4oZmVjdW5kaXR5X3Jlc2lkcykKCmBgYAoKYGBge3Igc3VwcC1maWctY3RtYXgtdGltZS1pbi1sYWIsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xMH0KIyBDb3BlcG9kcyBzcGVudCBzZXZlcmFsIGRheXMgaW4gbGFiIGR1cmluZyBleHBlcmltZW50cy4gU2hvd24gYmVsb3cgYXJlIHRoZSBDVG1heCByZXNpZHVhbHMgKHRha2VuIGZyb20gYSBtb2RlbCBvZiBDVG1heCBhZ2FpbnN0IGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUpIHBsb3R0ZWQgYWdhaW5zdCB0aGUgdGltZSBzcGVudCBpbiBsYWIgYmVmb3JlIG1lYXN1cmVtZW50cyB3ZXJlIG1hZGUuIEluZGl2aWR1YWwgcmVncmVzc2lvbnMgYXJlIHNob3duIGZvciB0aGUgcmVzaWR1YWxzIGFnYWluc3QgZGF5cyBpbiBsYWIgZm9yIGVhY2ggY29sbGVjdGlvbi4gV2UgY2FuIHNlZSBjbGVhcmx5IHRoYXQgdGhlcm1hbCBsaW1pdHMgYXJlIGZhaXJseSBzdGFibGUgb3ZlciB0aW1lLiAKCgojIGdncGxvdChjdG1heF9yZXNpZHMsIGFlcyh4ID0gZGF5c19pbl9sYWIsIHkgPSByZXNpZHMsIGNvbG91ciA9IHNwX25hbWUsIGdyb3VwID0gY29sbGVjdGlvbl9kYXRlKSkgKyAKIyAgIGZhY2V0X3dyYXAoc3BfbmFtZX4uKSArIAojICAgZ2VvbV9wb2ludChzaXplID0gNCwgYWxwaGEgPSAwLjUpICsgCiMgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDEpICsgCiMgICAjc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMDo1KSkgKyAKIyAgIGxhYnMoeCA9ICJEYXlzIGluIGxhYiIsIAojICAgICAgICB5ID0gIkNUbWF4IFJlc2lkdWFscyIpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciBzdXBwLWZpZy1tb2RlbC1wZXJmb3JtYW5jZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MTN9Cgptb2RlbF9kYXRhID0gZnVsbF9kYXRhICU+JSAgCiAgZHJvcF9uYShzaXplLCBjdG1heCkgJT4lICAKICBmaWx0ZXIoc3BfbmFtZSAhPSAiT3NwaHJhbnRpY3VtIGxhYnJvbmVjdHVtIikgJT4lIAogIG11dGF0ZSh0ZW1wX2NlbnQgPSBzY2FsZShjb2xsZWN0aW9uX3RlbXAsIGNlbnRlciA9IFQsIHNjYWxlID0gRiksCiAgICAgICAgIHNpemVfY2VudCA9IHNjYWxlKHNpemUsIGNlbnRlciA9IFQsIHNjYWxlID0gRikpCgptaW5pbWFsLm1vZGVsID0gbG1lNDo6bG1lcihkYXRhID0gbW9kZWxfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiBzcF9uYW1lICsgc2V4ICsgdGVtcF9jZW50ICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoMXxkYXlzX2luX2xhYikpCgpmdWxsLm1vZGVsID0gbG1lNDo6bG1lcihkYXRhID0gZmlsdGVyKG1vZGVsX2RhdGEsIHNwX25hbWUgIT0gIk9zcGhyYW50aWN1bSBsYWJyb25lY3R1bSIpLAogICAgICAgICAgICAgICAgICAgICAgICBjdG1heCB+IHNwX25hbWUqc2V4KnRlbXBfY2VudCArCiAgICAgICAgICAgICAgICAgICAgICAgICAgKDF8ZGF5c19pbl9sYWIpKQoKZHJvcDEoZnVsbC5tb2RlbCwgdGVzdCA9ICJDaGlzcSIpCgpwZXJmb3JtYW5jZTo6dGVzdF9wZXJmb3JtYW5jZShtaW5pbWFsLm1vZGVsLCBmdWxsLm1vZGVsKQpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoZnVsbC5tb2RlbCkKCmNhcjo6QW5vdmEoZnVsbC5tb2RlbCwgdHlwZSA9ICJJSUkiKQoKc3BfY3RtYXggPSBlbW1lYW5zOjplbW1lYW5zKGZ1bGwubW9kZWwsIHNwZWNzID0gInNwX25hbWUiKSAlPiUgCiAgZGF0YS5mcmFtZSgpICU+JSAKICBzZWxlY3Qoc3BfbmFtZSwgInNwZWNpZXNfY3RtYXgiID0gZW1tZWFuKQoKbW9kZWxfY29lZnMgPSBlbW1lYW5zOjplbXRyZW5kcyhmdWxsLm1vZGVsLCB2YXIgPSAidGVtcF9jZW50Iiwgc3BlY3MgPSAic3BfbmFtZSIpICU+JSAKICBkYXRhLmZyYW1lKCkgJT4lIAogIGlubmVyX2pvaW4oc3BfY3RtYXgpIAoKY3RtYXhfcmVzaWRzID0gbW9kZWxfZGF0YSAlPiUgCiAgbXV0YXRlKHJlc2lkcyA9IHJlc2lkdWFscyhmdWxsLm1vZGVsKSkKYGBgCgpgYGB7ciBtYWluLWZpZy1BUlItc3ludGgtcGxvdCwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9Nn0KYXJyX2NvbWJpbmVkID0gc3ludGhfYXJyICU+JQogIGZpbHRlcihtZWFzdXJlID09ICJ1cHBlciIgJiBtZWFuX2xpbSA+IDIwKSAlPiUgCiAgc2VsZWN0KCJncm91cCIgPSBnZW51cywgYXJyLCBtZWFuX2xpbSkgJT4lIAogIG11dGF0ZSgiZGF0YXNldCIgPSAic3ludGhlc2lzIikgJT4lIAogIGJpbmRfcm93cygKICAgIHNlbGVjdChtb2RlbF9jb2VmcywgImdyb3VwIiA9IHNwX25hbWUsICdhcnInID0gdGVtcF9jZW50LnRyZW5kLCAnbWVhbl9saW0nID0gc3BlY2llc19jdG1heCkKICApICU+JSAKICBtdXRhdGUoZGF0YXNldCA9IGlmX2Vsc2UoaXMubmEoZGF0YXNldCksICJuZXcgZGF0YSIsICJzeW50aGVzaXMiKSwKICAgICAgICAgZ3JvdXAgPSBmY3RfcmVvcmRlcihncm91cCwgYXJyLCAuZGVzYyA9IFQpKQoKCmdncGxvdChhcnJfY29tYmluZWQsIGFlcyh4ID0gbWVhbl9saW0sIHkgPSBhcnIpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgCiAgICAgICAgICAgICAgbGluZXdpZHRoID0gMiwgY29sb3VyID0gImdyZXkzMCIpICsgCiAgZ2VvbV9wb2ludChkYXRhID0gZmlsdGVyKGFycl9jb21iaW5lZCwgZGF0YXNldCAhPSAibmV3IGRhdGEiKSwgCiAgICAgICAgICAgICBzaXplID0gNCwgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoZGF0YSA9IGZpbHRlcihhcnJfY29tYmluZWQsIGRhdGFzZXQgPT0gIm5ldyBkYXRhIiksCiAgICAgICAgICAgICBhZXMoY29sb3VyID0gZ3JvdXApLCAKICAgICAgICAgICAgIHNpemUgPSA0KSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJUaGVybWFsIExpbWl0IiwgCiAgICAgICB5ID0gIkFSUiIsIAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmBgYAoKIyMjIFNleCBhbmQgc3RhZ2UgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzIApQcmV2aW91cyBzZWN0aW9ucyBoYXZlIGdlbmVyYWxseSBsdW1wZWQganV2ZW5pbGUsIGZlbWFsZSwgYW5kIG1hbGUgaW5kaXZpZHVhbHMgdG9nZXRoZXIuIFRoZXJlIG1heSBiZSBpbXBvcnRhbnQgc3RhZ2UtIG9yIHNleC1zcGVjaWZpYyBkaWZmZXJlbmNlcyBpbiBDVG1heCB0aG91Z2guIEZvciBhbGwgc3BlY2llcyBidXQgT3NwaHJhbnRpY3VtLCB3ZSBoYXZlIG1lYXN1cmVtZW50cyBmb3IgaW5kaXZpZHVhbHMgaW4gZGlmZmVyZW50IHN0YWdlcyBhbmQgb2YgZGlmZmVyZW50IHNleGVzLiAKCmBgYHtyIHNleC1zdGFnZS10YWJsZX0Kc2V4X3NhbXBsZV9zaXplcyA9IGZ1bGxfZGF0YSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUsIHNleCkgJT4lICAKICBzdW1tYXJpc2UobnVtID0gbigpKSAlPiUgIAogIHBpdm90X3dpZGVyKGlkX2NvbHMgPSBzcF9uYW1lLAogICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBzZXgsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gbnVtLAogICAgICAgICAgICAgIHZhbHVlc19maWxsID0gMCkgJT4lIAogIHNlbGVjdCgiU3BlY2llcyIgPSBzcF9uYW1lLCAiSnV2ZW5pbGUiID0ganV2ZW5pbGUsICJGZW1hbGUiID0gZmVtYWxlLCAiTWFsZSIgPSBtYWxlKQoKa25pdHI6OmthYmxlKHNleF9zYW1wbGVfc2l6ZXMsIGFsaWduID0gImMiKQpgYGAKCkFjcm9zcyBncm91cCBjb21wYXJpc29ucyBzaG93IHRoYXQgdGhlcmUgYXJlIGdlbmVyYWxseSBubyBkaWZmZXJlbmNlcyBpbiB0aGVybWFsIGxpbWl0cyAocmVwcmVzZW50ZWQgaGVyZSBhcyB0aGUgcmVzaWR1YWxzIGZyb20gYSBDVG1heCB+IGNvbGxlY3Rpb25fdGVtcCB4IHNwZWNpZXMgbGluZWFyIHJlZ3Jlc3Npb24pLCB3aXRoIHRoZSBleGNlcHRpb24gb2YgU2VuZWNlbGxhIG1hbGVzLCB3aGljaCBtYXkgaGF2ZSBsb3dlciB0aGVybWFsIGxpbWl0cyAoYWx0aG91Z2ggc2FtcGxlIHNpemVzIGFyZSB2ZXJ5IHNtYWxsIGluIHRoaXMgZ3JvdXApLgoKYGBge3Igc3VwcC1maWctY3RtYXgtc2V4LCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9OH0KIyBjdG1heF9yZXNpZHMgJT4lIAojICAgZmlsdGVyKHNwX25hbWUgIT0gIk9zcGhyYW50aWN1bSBsYWJyb25lY3R1bSIpICU+JSAKIyAgIGdncGxvdChhZXMoeCA9IHNleCwgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSkpICsgCiMgICBmYWNldF93cmFwKHNwX25hbWV+LikgKyAKIyAgIGdlb21faml0dGVyKHdpZHRoID0gMC4xLCBhbHBoYSA9IDAuNSkgKyAKIyAgIGdlb21fYm94cGxvdCh3aWR0aCA9IDAuNCwgZmlsbCA9IE5BLCBjb2xvdXIgPSAiYmxhY2siLCAKIyAgICAgICAgICAgICAgICBsaW5ld2lkdGggPSAxLCBvdXRsaWVyLmNvbG91ciA9IE5BKSArIAojICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiMgICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKYGBge3IgdHJhaXQtdmFyaWFuY2UtY29sbC10ZW1wLCBpbmNsdWRlID0gRn0KIyAKIyBHaXZlbiB0aGUgbG9uZyBnZW5lcmF0aW9uIHRpbWVzIG9mIHRoZXNlIGNvcGVwb2RzLCBkZWNyZWFzZXMgaW4gdHJhaXQgdmFyaWFuY2UgbWF5IGluZGljYXRlIHNlbGVjdGlvbiBvdmVyIHRoZSBzZWFzb25hbCBjeWNsZS4gU2hvd24gYmVsb3cgYXJlIHRoZSB2YXJpYW5jZSBpbiBvYnNlcnZlZCBDVG1heCBhbmQgc2l6ZSwgcGxvdHRlZCBhZ2FpbnN0IGNvbGxlY3Rpb24gZGF0ZS4gVmFyaWFuY2UgZGVjcmVhc2VzIGluICpTa2lzdG9kaWFwdG9tdXMqLCBidXQgdGhpcyBwYXR0ZXJuIGlzIGRyaXZlbiBieSBhIHNpbmdsZSBjb2xsZWN0aW9uIHdpdGggaGlnaCB2YXJpYW5jZSBlYXJseSBpbiB0aGUgeWVhci4gU2l6ZSB2YXJpYW5jZSBpbmNyZWFzZXMgc2xpZ2h0bHkgaW4gKlNraXN0b2RpYXB0b211cyouIFZhcmlhbmNlIGluIGJvdGggQ1RtYXggYW5kIHNpemUgaXMgZmFpcmx5IGNvbnN0YW50IGluICpMZXB0b2RpYXB0b211cyBtaW51dHVzKiwgdGhlIG9ubHkgb3RoZXIgc3BlY2llcyBjb2xsZWN0ZWQgYWNyb3NzIHRoZSBlbnRpcmUgc2V0IG9mIHNhbXBsZXMgdGh1cyBmYXIuIAojIAojIGdncGxvdChkcm9wX25hKGFkdWx0X3N1bW1hcmllcywgY3RtYXhfdmFyKSwgYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBjdG1heF92YXIsIGNvbG91ciA9IHNwX25hbWUpKSArIAojICAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIHNjYWxlcyA9ICJmcmVlX3kiKSArIAojICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKIyAgIGdlb21fc21vb3RoKHNlID0gRikgKyAKIyAgIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIiwgCiMgICAgICAgIHkgPSAiQ1RtYXggVmFyaWFuY2UiKSArIAojICAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiMgICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiMgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiMgCiMgZ2dwbG90KGRyb3BfbmEoYWR1bHRfc3VtbWFyaWVzLCBzaXplX3ZhciksIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gc2l6ZV92YXIsIGNvbG91ciA9IHNwX25hbWUpKSArIAojICAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiMgICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAojICAgZ2VvbV9zbW9vdGgoc2UgPSBGKSArIAojICAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcC4gKMKwQykiLCAKIyAgICAgICAgeSA9ICJTaXplIFZhcmlhbmNlIikgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAojICAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCmBgYHtyIHN1cHAtZmlnLW1vZGVsMi1wZXJmb3JtYW5jZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9MTN9Cm1vZGVsMl9kYXRhID0gbW9kZWxfZGF0YSAlPiUgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIiwgCiAgICAgICAgIHBhdGhvZ2VuICE9ICJ1bmNlcnRhaW4iLCAKICAgICAgICAgZGV2X2VnZ3MgIT0gInVuY2VydGFpbiIsIAogICAgICAgICBsaXBpZHMgIT0gInVuY2VydGFpbiIpICU+JSAKICBtdXRhdGUocGF0aG9nZW5zID0gZmN0X3JlbGV2ZWwocGF0aG9nZW4sICJubyIsICJzcG90IiwgImNsb3VkeSIsICJvdGhlciIpKQoKb3RoZXJfZmFjdG9yX21vZGVsID0gbG1lcihkYXRhID0gbW9kZWwyX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgICAgIGN0bWF4fnNwX25hbWUgKiBjb2xsZWN0aW9uX3RlbXAgKyBkZXZfZWdncyArIHBhdGhvZ2VuICsgbGlwaWRzICsgKDF8ZGF5c19pbl9sYWIpKQoKZHJvcDEob3RoZXJfZmFjdG9yX21vZGVsLCBzY29wZSA9IH4uLCB0ZXN0ID0gIkNoaXNxIikKCnJlZHVjZWRfZmFjdG9yc19tb2RlbCA9IGxtZXIoZGF0YSA9IG1vZGVsMl9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjdG1heH5zcF9uYW1lICogY29sbGVjdGlvbl90ZW1wICsgcGF0aG9nZW4gKyAoMXxkYXlzX2luX2xhYikpCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwocmVkdWNlZF9mYWN0b3JzX21vZGVsKQpgYGAKCmBgYHtyIHN1cHAtZmlnLXBhdGhvZ2VuLWVmZmVjdCwgZmlnLndpZHRoPTgsIGZpZy5oZWlnaHQ9NX0KZW1tZWFuczo6ZW1tZWFucyhyZWR1Y2VkX2ZhY3RvcnNfbW9kZWwsIHNwZWMgPSAicGF0aG9nZW4iKSAlPiUgZW1tZWFuczo6Y29udHJhc3QobWV0aG9kPSJ0cnQudnMuY3RybCIscmVmPSJubyIpICU+JSBwbG90KCkgKyAKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwKSArIAogIGxhYnMoeCA9ICJEaWZmZXJlbmNlICjCsEMpIiwgCiAgICAgICB5ID0gIkNvbXBhcmlzb24iKSArIAogICAgdGhlbWVfbWF0dCgpCmBgYAoKCgojIyMgVHJhaXQgQ29ycmVsYXRpb25zIGFuZCBUcmFkZS1vZmZzCgpBIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNpemUgYW5kIHVwcGVyIHRoZXJtYWwgbGltaXRzIGhhcyBiZWVuIHN1Z2dlc3RlZCBpbiBhIHdpZGUgcmFuZ2Ugb2Ygb3RoZXIgdGF4YS4gU2hvd24gYmVsb3cgYXJlIHRoZSBtZWFzdXJlZCB1cHBlciB0aGVybWFsIGxpbWl0cyBwbG90dGVkIGFnYWluc3QgcHJvc29tZSBsZW5ndGguIFRoZSBvdmVyYWxsIHJlbGF0aW9uc2hpcCAoaW5jbHVzaXZlIG9mIGFsbCBzcGVjaWVzKSBpcyBzaG93biBhcyB0aGUgYmxhY2sgbGluZSBpbiB0aGUgYmFja2dyb3VuZC4gUmVncmVzc2lvbnMgZm9yIGVhY2ggaW5kaXZpZHVhbCBzcGVjaWVzIGFyZSBhbHNvIHNob3duLiBBY3Jvc3MgdGhlIGVudGlyZSBhc3NlbWJsYWdlLCB0aGVyZSBpcyBhIHN0cm9uZyBkZWNyZWFzZSBpbiB0aGVybWFsIGxpbWl0cyB3aXRoIGluY3JlYXNpbmcgc2l6ZS4gIAoKYGBge3IgbWlzYy1jdG1heC1zaXplLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KZnVsbF9kYXRhICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBnZ3Bsb3QoIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuMykgKyAKICBnZW9tX3Ntb290aChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwgCiAgICAgICAgICAgICAgY29sb3VyID0iYmxhY2siLCAKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLjUpICsgCiAgbGFicyh4ID0gIkxlbmd0aCAobW0pIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKYGBgCgpTaG93biBoZXJlIGlzIHRoZSByZWxhdGlvbnNoaXAgZm9yIGVhY2ggc3BlY2llcyBpbmRpdmlkdWFsbHkuIAoKYGBge3IgbWlzYy1pbmQtc3AtY3RtYXgtc2l6ZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9Nn0KZnVsbF9kYXRhICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgZmlsdGVyKG4oKSA+MikgJT4lIGZpbHRlcighc3RyX2RldGVjdChzcF9uYW1lLCBwYXR0ZXJuID0gImtpbmR0aSIpKSAlPiUgCiAgZ2dwbG90KCBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIHNjYWxlcyA9ICJmcmVlIiwgbnJvdyA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAyKSArIAogIGxhYnMoeCA9ICJMZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKClNob3duIGJlbG93IGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBtZWFuIHNpemUgYW5kIG1lYW4gdGhlcm1hbCBsaW1pdHMgZm9yIGZlbWFsZXMgb2YgZWFjaCBzcGVjaWVzLiBXZSBzZWUgdGhhdCBsYXJnZXIgc3BlY2llcyB3aXRoaW4gdGhlIGNvbW11bml0eSB0ZW5kIHRvIGhhdmUgYSBsb3dlciB0aGVybWFsIGxpbWl0IHRoYW4gc21hbGxlciBzcGVjaWVzLiAKCmBgYHtyIG1haW4tZmlnLW1lYW4tY3RtYXgtbWVhbi1zaXplLXBsb3QsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTV9CmZ1bGxfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoc3BfbmFtZSwgc2V4KSAlPiUgCiAgc3VtbWFyaXplKG1lYW5fY3RtYXggPSBtZWFuKGN0bWF4LCBuYS5ybSA9IFQpLAogICAgICAgICAgICBtZWFuX3NpemUgPSBtZWFuKHNpemUsIG5hLnJtID0gVCkpICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IG1lYW5fc2l6ZSwgeSA9IG1lYW5fY3RtYXgpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMiwgY29sb3VyID0gImJsYWNrIikgKyAKICBnZW9tX3BvaW50KGFlcyhjb2xvdXIgPSBzcF9uYW1lLCBzaGFwZSA9IHNleCksCiAgICAgICAgICAgICBzaXplID0gNSkgKyAKICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKYGBge3IgY3RtYXhyZXNpZHMtc2l6ZSwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTcsIGluY2x1ZGUgPSBGfQojIGN0bWF4X3Jlc2lkcyAlPiUgCiMgICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gc2l6ZSwgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSkpICsgCiMgICBmYWNldF93cmFwKHNwX25hbWV+LikgKyAKIyAgIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgCiMgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiMgICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKIyAgICAgICAgeSA9ICJDVG1heCAowrBDKSIpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHRoZW1lX21hdHQoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKClNob3duIGhlcmUgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGZlY3VuZGl0eSBhbmQgc2l6ZSwgc2hvd2luZyB0aGUgY2xhc3NpYyBwYXR0ZXJuIG9mIGluY3JlYXNpbmcgZWdnIHByb2R1Y3Rpb24gd2l0aCBpbmNyZWFzaW5nIHNpemUuIAoKYGBge3IgZmVjdW5kaXR5LXNpemV9CnNpemVfZmVjdW5kX3Bsb3QgPSBjdG1heF9yZXNpZHMgJT4lICAKICBkcm9wX25hKGZlY3VuZGl0eSkgJT4lIAogIGdncGxvdChhZXMoeCA9IHNpemUsIHkgPSBmZWN1bmRpdHksIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuNSkgKyAKICBsYWJzKHggPSAiUHJvc29tZSBsZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKSW5kaXZpZHVhbHMgbWF5IGFsc28gYWxsb2NhdGUgZW5lcmd5IHRvIGRpZmZlcmVudCBmaXRuZXNzIHJlbGF0ZWQgdHJhaXRzLCBwcmlvcml0aXppbmcgcmVwcm9kdWN0aXZlIG91dHB1dCBvdmVyIGVudmlyb25tZW50YWwgdG9sZXJhbmNlLCBmb3IgZXhhbXBsZS4gU2hvd24gYmVsb3cgaXMgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIENUbWF4IHJlc2lkdWFscyAoYWdhaW4sIGNvbnRyb2xsaW5nIGZvciB0aGUgZWZmZWN0cyBvZiBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlKSBhZ2FpbnN0IGZlY3VuZGl0eS4gV2UgY2FuIHNlZSBjbGVhcmx5IHRoYXQgaW5kaXZpZHVhbHMgd2l0aCBpbmNyZWFzZWQgZmVjdW5kaXR5IGFyZSBub3QgZGVjcmVhc2luZyB0aGVybWFsIGxpbWl0cywgc3VnZ2VzdGluZyB0aGF0IHRoZXJlIGlzIG5vIGVuZXJnZXRpYyB0cmFkZS1vZmYgYmV0d2VlbiB0aGVzZSB0cmFpdHMuIApgYGB7ciwgbWFpbi1maWctZmVjdW5kaXR5LXBsb3RzLCBmaWcud2lkdGg9OC41LCBmaWcuaGVpZ2h0PTEwfQpjdG1heF9mZWN1bmRfcGxvdCA9IGN0bWF4X3Jlc2lkcyAlPiUgIAogIGRyb3BfbmEoZmVjdW5kaXR5KSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gcmVzaWRzLCB5ID0gZmVjdW5kaXR5LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjUpICsgCiAgbGFicyh4ID0gIkNUbWF4IFJlc2lkdWFscyAowrBDKSIsIAogICAgICAgeSA9ICJGZWN1bmRpdHkgKCMgRWdncykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpnZ2FycmFuZ2Uoc2l6ZV9mZWN1bmRfcGxvdCwgY3RtYXhfZmVjdW5kX3Bsb3QsIG5jb2wgPSAxLCBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgpQcmV2aW91cyBzdHVkaWVzIGhhdmUgc2hvd24gdGhhdCB0aGUgbWFnbml0dWRlIG9mIHRoZSBzaXplLWZlY3VuZGl0eSBjb3JyZWxhdGlvbiBtYXkgYmUgZW52aXJvbm1lbnRhbGx5LWRlcGVuZGVudC4gVGhpcyBpcyBub3QgdmlzaWJsZSBpcyB0aGUgZGF0YSBmcm9tIHRoZXNlIGNvbGxlY3Rpb25zLiAKCmBgYHtyIHN1cHAtZmlnLWZlYy1zaXplLWNvcnItdnMtdGVtcCwgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodD0xMH0KY29ycl9kYXRhID0gZnVsbF9kYXRhICU+JSAKICBkcm9wX25hKGZlY3VuZGl0eSkgJT4lIAogIGZpbHRlcihzcF9uYW1lICVpbiUgYygiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICJMZXB0b2RpYXB0b211cyBtaW51dHVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICJTa2lzdG9kaWFwdG9tdXMgc3AiKSkgJT4lICAKICBncm91cF9ieShjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCwgc3BfbmFtZSkgJT4lIAogIHN1bW1hcmlzZShzaXplX2ZlY19jb3JyID0gY29yKHNpemUsIGZlY3VuZGl0eSksCiAgICAgICAgICAgIG4gPSBuKCksCiAgICAgICAgICAgIG1lYW5fZmVjdW5kaXR5ID0gbWVhbihmZWN1bmRpdHkpKSAlPiUgCiAgZmlsdGVyKG4gPj0gMykgJT4lIAogIHVuZ3JvdXAoKSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSAKICBtdXRhdGUodGVtcF9jZW50ID0gc2NhbGUoY29sbGVjdGlvbl90ZW1wLCBzY2FsZSA9IEYpKQoKZ2dwbG90KGNvcnJfZGF0YSwgYWVzKHggPSB0ZW1wX2NlbnQsIHkgPSBzaXplX2ZlY19jb3JyLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKHNwX25hbWV+LiwgbnJvdyA9IDMpICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMikgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJUZW1wZXJhdHVyZSAoY2VudGVyZWQpIiwgCiAgICAgICB5ID0gIkNvcnJlbGF0aW9uIENvZWZmaWNpZW50IikgKyAKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoLTEsIDEpKSArCiAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCiMgZ2dwbG90KGNvcnJfZGF0YSwgYWVzKHggPSBzaXplX2ZlY19jb3JyKSkgKwojICAgICBmYWNldF93cmFwKHNwX25hbWV+LiwgbnJvdyA9IDMpICsKIyAgIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMC4yKQpgYGAKCgojIyBPdGhlciBwYXR0ZXJucyBpbiB2YXJpYXRpb24gCgoqTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyogaXMgdGhlIG1vc3QgYWJ1bmRhbnQgc3BlY2llcyBkdXJpbmcgdGhlIHdpbnRlci4gVGhlcmUgd2FzIGEgbGFyZ2Ugc2hpZnQgaW4gdGhlIHNpemUgb2YgbWF0dXJlIGZlbWFsZXMgdG93YXJkcyB0aGUgZW5kIG9mIERlY2VtYmVyLiBUaGVzZSBsYXJnZSBhbmQgc21hbGwgaW5kaXZpZHVhbHMgYXJlIHRoZSBzYW1lIHNwZWNpZXMgKGNvbmZpcm1lZCB2aWEgQ09JIHNlcXVlbmNpbmcpLCBzdWdnZXN0aW5nIHRoaXMgc2hpZnQgbWF5IGluc3RlYWQgcmVmbGVjdCBhIHRyYW5zaXRpb24gZnJvbSBvbmUgZ2VuZXJhdGlvbiB0byBhbm90aGVyLiBUaGlzIHNpemUgZGlmZmVyZW5jZSBtYXkgYmUgY2F1c2VkIGJ5IGRpZmZlcmVuY2VzIGluIHRoZSBkZXZlbG9wbWVudGFsIGVudmlyb25tZW50cy4gRm9yIGV4YW1wbGUsIGluZGl2aWR1YWxzIGRldmVsb3BpbmcgaW4gSmFudWFyeSBncm93IHVwIGF0IHZlcnkgbG93IHRlbXBlcmF0dXJlcywgYW5kIHRoZXJlZm9yZSBtYXkgcmVhY2ggbGFyZ2VyIHNpemVzLiBUaGVzZSBpbmRpdmlkdWFscyBvdmVyLXN1bW1lciBpbiBkZWVwIHdhdGVycywgdGhlbiByZS1lbWVyZ2UgaW4gT2N0b2JlciBhbmQgcHJvZHVjZSBhIG5ldyBnZW5lcmF0aW9uLiBXYXRlciB0ZW1wZXJhdHVyZXMgYXJlIHN0aWxsIGZhaXJseSBoaWdoIHRocm91Z2ggTm92ZW1iZXIsIHdoaWNoIHJlc3VsdHMgaW4gYSBnZW5lcmF0aW9uIG9mIHNtYWxsZXIgaW5kaXZpZHVhbHMuIFRoZXNlIGluZGl2aWR1YWxzIG1hdHVyZSBpbiB0aW1lIHRvIHByb2R1Y2UgYSBuZXcgZ2VuZXJhdGlvbiBpbiBKYW51YXJ5LiAKCmBgYHtyIHN1cHAtZmlnLWxzaWMtbW9ycGgtc2l6ZSwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9OX0KZnVsbF9kYXRhICU+JSAgCiAgZmlsdGVyKHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiKSAlPiUgCiAgZmlsdGVyKHNleCAhPSAianV2ZW5pbGUiKSAlPiUgCiAgZ3JvdXBfYnkoY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgbXV0YXRlKHNpemVfY2VudGVyID0gc2NhbGUoc2l6ZSwgY2VudGVyID0gVCwgc2NhbGUgPSBGKSkgJT4lIAogIGdncGxvdChhZXMoeSA9IGZhY3Rvcihjb2xsZWN0aW9uX2RhdGUpLCB4ID0gc2l6ZSwgZmlsbCA9IGNvbGxlY3Rpb25fdGVtcCkpICsgCiAgZmFjZXRfd3JhcChzZXh+LikgKyAKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKGJhbmR3aWR0aCA9IDAuMDQpICsgCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMC44OSkgKyAKICBsYWJzKHggPSAiU2l6ZSAobW0pIiwKICAgICAgIHkgPSAiRGF0ZSIsIAogICAgICAgZmlsbCA9ICJDb2xsLiBUZW1wLiAowrBDKSIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IiwKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIpKQpgYGAKCkEgc2ltaWxhciwgYnV0IGxlc3MgZGlzdGluY3QgcGF0dGVybiBjYW4gYmUgb2JzZXJ2ZWQgaW4gTC4gbWludXR1cyBpbmRpdmlkdWFscyBhcyB3ZWxsLiAKYGBge3Igc3VwcC1maWctbG1pbi1tb3JwaC1zaXplLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD05fQpmdWxsX2RhdGEgJT4lICAKICBmaWx0ZXIoc3BfbmFtZSA9PSAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyIpICU+JSAKICBmaWx0ZXIoc2V4ICE9ICJqdXZlbmlsZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSBmYWN0b3IoY29sbGVjdGlvbl9kYXRlKSwgeCA9IHNpemUsIGZpbGwgPSBjb2xsZWN0aW9uX3RlbXApKSArIAogIGZhY2V0X3dyYXAoc2V4fi4pICsgCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhiYW5kd2lkdGggPSAwLjA0KSArIAogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuNjkpICsgCiAgbGFicyh4ID0gIlNpemUgKG1tKSIsCiAgICAgICB5ID0gIkRhdGUiLCAKICAgICAgIGZpbGwgPSAiQ29sbC4gVGVtcC4gKMKwQykiKSArIAogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLjUsMC45KSkgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpCmBgYAoKIyMgRGlzdHJpYnV0aW9uIExhZyBOb24tTGluZWFyIE1vZGVsIChETE5NIGFwcHJvYWNoKSAKCkRpc3RyaWJ1dGVkIGxhZyBtb2RlbHMgZXhhbWluZSBhIHJlc3BvbnNlIHZhcmlhYmxlLCBtZWFzdXJlZCBhdCBtdWx0aXBsZSB0aW1lIHBvaW50cywgYXMgYSBmdW5jdGlvbiBvZiB0aGUgbGFnZ2VkIG9jY3VycmVuY2Ugb2Ygc29tZSBwcmVkaWN0b3IgdmFyaWFibGUgKHJlc3BvbnNlIHkgYXQgdGltZSB0IGFzIGEgZnVuY3Rpb24gb2YgcHJlZGljdG9yIHgodC1sYWcpLiBUaGlzIG1ldGhvZCB1dGlsaXplcyBhIGJpLWRpbWVuc2lvbmFsIGRvc2UtbGFnLXJlc3BvbnNlIGZ1bmN0aW9uLCB3aGljaCBlc3NlbnRpYWxseSBleGFtaW5lcyBub3Qgb25seSB0aGUgZG9zZSBlZmZlY3QsIGJ1dCB0aGUgZWZmZWN0IG9mIHRoZSB0aW1pbmcgb2YgdGhlIGRvc2UuIAoKCmBgYHtyIGNvbXBpbGluZ190ZW1wX2xhZ3N9CiMgUnVuIHRoaXMgY29kZSwgc2F2ZSB0aGUgcHJvZHVjdCwgYW5kIHRoZW4ganVzdCByZWFkIGluIHRoZSB0ZW1wIGxhZyBkYXRhIG9iamVjdC4gVGFrZXMgdG9vIGxvbmcgdG8gcnVuIGVhY2ggdGltZSB0aGlzIGRvY3VtZW50IGlzIGtuaXQuIAoKIyBsYWdfdGVtcHMgPSB0ZW1wX2RhdGEgJT4lCiMgICBncm91cF9ieShkYXRlLCBob3VyKSAlPiUKIyAgIHN1bW1hcml6ZSgibWVhbl90ZW1wIiA9IG1lYW4odGVtcCwgbmEucm0gPSBUKSkgJT4lCiMgICB1bmdyb3VwKCkgJT4lCiMgICBtdXRhdGUocG9pbnRfbnVtID0gcm93X251bWJlcigpKQojIAojIHVuaXFfZGF5cyA9IGxlbmd0aCh1bmlxdWUobGFnX3RlbXBzJGRhdGUpKQojIAojIGcgPSBnYW0obWVhbl90ZW1wIH4gcyhwb2ludF9udW0sIGJzPSJjciIsIGs9dW5pcV9kYXlzICsgMTApLAojICAgICBtZXRob2QgPSAiUkVNTCIsCiMgICAgIGRhdGEgPSBsYWdfdGVtcHMpCiMgCiMgcG9pbnRzID0gc2VxKDEsIG5yb3cobGFnX3RlbXBzKSwgbGVuZ3RoLm91dCA9IGxlbmd0aChsYWdfdGVtcHMkaG91cikpCiMgCiMgZGYucmVzID0gZGYucmVzaWR1YWwoZykKIyAKIyBwcmVkX3RlbXBzID0gcHJlZGljdChnLCBuZXdkYXRhID0gbGFnX3RlbXBzLCB0eXBlID0gInJlc3BvbnNlIiwgc2UuZml0ID0gVFJVRSkKIyAKIyBsYWdfdGVtcHMgPSBsYWdfdGVtcHMgJT4lCiMgICBtdXRhdGUodHJlbmRfVCA9IHByZWRfdGVtcHMkZml0LAojICAgICAgICAgIHRyZW5kX3NlID0gcHJlZF90ZW1wcyRzZS5maXQsCiMgICAgICAgICAgdGVtcF9kaWZmID0gbWVhbl90ZW1wIC0gdHJlbmRfVCkKIyAKIyB3cml0ZS5jc3YobGFnX3RlbXBzLCBmaWxlID0gIi4vT3V0cHV0L0RhdGEvbGFnX3RlbXBzLmNzdiIsIHJvdy5uYW1lcyA9IEYpCgpgYGAKCmBgYHtyIHN1cHAtZmlnLWRhaWx5LW1heC1jdG1heCwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NH0gCgpkbG5tX2RhdGEgPSBmdWxsX2RhdGEgJT4lICAKICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBjKAogICAgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiLAogICAgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiLAogICAgIlNraXN0b2RpYXB0b211cyBzcCIKICApKSAlPiUgCiAgc2VsZWN0KGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wLCBzcF9uYW1lLCBjdG1heCkgJT4lIAogIGdyb3VwX2J5KGNvbGxlY3Rpb25fZGF0ZSwgY29sbGVjdGlvbl90ZW1wLCBzcF9uYW1lKSAlPiUgIAogIHN1bW1hcmlzZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCwgbmEucm0gPSBUKSwKICAgICAgICAgICAgc2FtcGxlID0gbigpKQoKdGVtcF9kYXRhICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXNlKG1lYW5fdGVtcCA9IG1lYW4odGVtcCksCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXAsIG5hLnJtID0gVCkpICU+JSAKICByaWdodF9qb2luKGRsbm1fZGF0YSwgYnkgPSBqb2luX2J5KCJkYXRlIiA9PSAiY29sbGVjdGlvbl9kYXRlIikpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBtYXhfdGVtcCwgeSA9IG1lYW5fY3RtYXgpKSArIAogIGZhY2V0X3dyYXAoLn5zcF9uYW1lKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJnYW0iKSArIAogIGdlb21fcG9pbnQoKSArIAogIGxhYnMoeCA9ICJNYXggRGFpbHkgVGVtcC4gKMKwQykiLAogICAgICAgeSA9ICJNZWFuIENUbWF4ICjCsEMpIikgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMikpCmBgYAoKYGBge3Igc3VwcC1maWctZGxubS1wbG90fQoKc3BfbGlzdCA9IHVuaXF1ZShkbG5tX2RhdGEkc3BfbmFtZSkKCmZvcihsYWdfc3BlY2llcyBpbiBzcF9saXN0KXsKICAKICBkbG5tX2RhdGFfc3AgPSBkbG5tX2RhdGEgJT4lIAogICAgZmlsdGVyKHNwX25hbWUgPT0gbGFnX3NwZWNpZXMpCiAgCiAgIyBXZSBuZWVkIHRvIGVzdGltYXRlIGEgbWF0cml4IG9mIGV4cG9zdXJlIGhpc3RvcmllcyBmb3IgZWFjaCBvYnNlcnZhdGlvbi4gVGhpcyBjb250YWlucyB0aGUgc2VyaWVzIG9mIGV4cG9zdXJlcyBhdCBlYWNoIGxhZyAobCkgZm9yIGVhY2ggb2YgdGhlIG4gb2JzZXJ2YXRpb25zLCBjb25zdHJhaW5lZCBiZXR3ZWVuIGwwIChtaW5pbXVtIGxhZykgYW5kIEwgKG1heCBsYWcpLiAKICAKICBkYXRlcyA9IGRsbm1fZGF0YV9zcCRjb2xsZWN0aW9uX2RhdGUgIyBGb3IgZWFjaCBvZiB0aGVzZSBkYXRlcywgbWFrZSBhIHZlY3RvciBvZiB0aGUgcGFzdCAzMCBkYXlzIChpbmNsdWRpbmcgdGhlIGRheSBvZiBjb2xsZWN0aW9uKS4gTk9URTogRG9uJ3QgdXNlICd1bmlxdWUnIGRhdGVzIGhlcmUgc2luY2Ugc29tZSBjb2xsZWN0aW9ucyBoYWQgbXVsdGlwbGUgc3BlY2llcwogIAogIGV4cF9oaXN0X3ogPSBkYXRhLmZyYW1lKCkKICBleHBfaGlzdF90cmVuZCA9IGRhdGEuZnJhbWUoKQogIAogIGZvcihkIGluIGRhdGVzKXsKICAgIAogICAgaGlzdG9yeSA9IGxhZ190ZW1wcyAlPiUgCiAgICAgIGZpbHRlcihkYXRlIDw9IGQgJiBkYXRlID4gZCAtIDEwKSAlPiUgCiAgICAgIGFycmFuZ2UoZGVzYyhkYXRlKSwgZGVzYyhob3VyKSkgJT4lIAogICAgICBtdXRhdGUobGFnID0gcm93X251bWJlcigpIC0gMSkgJT4lIAogICAgICBzZWxlY3QobGFnLCBtZWFuX3RlbXAsIHRlbXBfZGlmZikKICAgIAogICAgel92ZWMgPSBzY2FsZShoaXN0b3J5JG1lYW5fdGVtcClbLDFdCiAgICBuYW1lcyh6X3ZlYykgPSBoaXN0b3J5JGxhZwogICAgCiAgICB0cmVuZF92ZWMgPSBoaXN0b3J5JHRlbXBfZGlmZgogICAgbmFtZXModHJlbmRfdmVjKSA9IGhpc3RvcnkkbGFnCiAgICAKICAgIGV4cF9oaXN0X3ogPSBiaW5kX3Jvd3MoZXhwX2hpc3Rfeiwgel92ZWMpCiAgICBleHBfaGlzdF90cmVuZCA9IGJpbmRfcm93cyhleHBfaGlzdF90cmVuZCwgdHJlbmRfdmVjKQogICAgCiAgfQogIAogICNwcmludChtYXgoZXhwX2hpc3RfdHJlbmQsIG5hLnJtID0gVCkpCiAgCiAgIyBUaGUgY3Jvc3MtYmFzaXMgZnVuY3Rpb24gZnJvbSBkbG5tIHdpbGwgdXNlIHRoZSBjbGFzcyBvZiB0aGUgeCBwYXJhbWV0ZXIgdG8gZGV0ZXJtaW5lIHdoYXQgdG8gZG8uIEluIG91ciBjYXNlLCB3ZSBuZWVkIHRvIHByb3ZpZGUgaXQgd2l0aCB0aGUgbWF0cml4IG9mIGV4cG9zdXJlIGhpc3RvcmllcyBmb3IgcmVhY2ggb2JzZXJ2YXRpb24gKHJvdykgYW5kIGxhZyAoY29sdW1uKS4gCiAgCiAgY2JfdGVtcHMgPSBjcm9zc2Jhc2lzKGV4cF9oaXN0X3RyZW5kLCBsYWcgPSBjKDAsZGltKGV4cF9oaXN0X3RyZW5kKVsyXS0xKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3ZhciA9bGlzdChmdW49ImNyIixkZj0zKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ2xhZz1saXN0KGZ1bj0iY3IiLGRmPTMsaW50ZXJjZXB0PVQpKQogIAogICNzdW1tYXJ5KGNiX3RlbXBzKQogIAogIHBlbmFsaXplZF9tYXQgPC0gY2JQZW4oY2JfdGVtcHMpCiAgCiAgI2ZpdHRpbmcgR0FNCiAgbGFnLmdhbSA9IGdhbShkYXRhID0gZGxubV9kYXRhX3NwLCAKICAgICAgICAgICAgICAgIG1lYW5fY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKyBjYl90ZW1wcywgCiAgICAgICAgICAgICAgICBtZXRob2QgPSAiR0NWLkNwIiwKICAgICAgICAgICAgICAgIHBhcmFQZW49bGlzdChjYl90ZW1wcz1wZW5hbGl6ZWRfbWF0KSkKICAKICAjIHN1bW1hcnkobGFnLmdhbSkKICAjIEFJQyhsYWcuZ2FtKQogIAogICNlc3RpbWF0aW9uIG9mIGV4cG9zdXJlcyBlZmZlY3RzCiAgCiAgI2RlZmF1bHQgcGxvdHMKICBwcmVkX2dhbV9aczwtY3Jvc3NwcmVkKGNiX3RlbXBzLCBsYWcuZ2FtLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGN1bXVsPUYsIGNlbj0wLCBjaS5sZXZlbCA9IDAuOTUsCiAgICAgICAgICAgICAgICAgICAgICAgICBhdD1zZXEoLTQsNCwgMC4xKSkKICAKICBwbG90KHByZWRfZ2FtX1pzLCAiY29udG91ciIsIG1haW4gPSBsYWdfc3BlY2llcykKICAjIAogICMgcGxvdChwcmVkX2dhbV9acywgYm9yZGVyID0gMiwgY3VtdWw9RiwKICAjICAgICAgIHRoZXRhPTExMCxwaGk9MjAsbHRoZXRhPS04MCkKICAKICBwbG90KHByZWRfZ2FtX1pzLCAic2xpY2VzIiwKICAgICAgIHZhciA9IGMoMywtMyksCiAgICAgICBsYWcgPSBjKDEsMjAwKSwKICAgICAgIGNvbCA9IDIpCiAgCn0KCgpgYGAKCgojIyBIaW5kY2FzdGluZyB2dWxuZXJhYmlsaXR5IHdpdGggZGlmZmVyZW50IGFjY2xpbWF0aW9uIHNjZW5hcmlvcwpVc2luZyB0aGUgb2JzZXJ2ZWQgdGhlcm1hbCBsaW1pdCBkYXRhLCB3ZSBjYW4gcHJvZHVjZSBhIGhpbmRjYXN0IG9mIHRoZXJtYWwgc3RyZXNzIGZvciBMYWtlIENoYW1wbGFpbiBjb3BlcG9kcy4gRm9yIHRoZXNlIGluaXRpYWwgYXNzYXlzLCB3ZSB3aWxsIGRlZmluZSB0aGVybWFsIHN0cmVzcyBhcyBhbnkgdGltZSB3aGVuIG1heGltdW0gZGFpbHkgd2F0ZXIgdGVtcGVyYXR1cmUgaXMgd2l0aGluIDXCsEMgb2YgY29wZXBvZCBDVG1heCBvciBoaWdoZXIgKGkuZS4gd2FybWluZyB0b2xlcmFuY2UgaXMgbGVzcyB0aGFuIDXCsEMpLiBXZSB3aWxsIHVzZSB0aHJlZSBkaWZmZXJlbnQgc2NlbmFyaW9zOiAxKSBlYWNoIHNwZWNpZXMgaGFzIGEgdW5pcXVlIGJ1dCBmaXhlZCB0aGVybWFsIGxpbWl0IChhdmVyYWdlIG1lYXN1cmVkIENUbWF4KSwgMikgc3BlY2llcyBoYXZlIHVuaXF1ZSB0aGVybWFsIGxpbWl0cyBhbmQgYXJlIGFibGUgdG8gYWNjbGltYXRlIChjb25zdGFudCBBUlIgYWNyb3NzIGFsbCBzcGVjaWVzIHVzZWQgdG8gcHJlZGljdCBDVG1heCBiYXNlZCBvbiBhdmVyYWdlIGRhaWx5IHRlbXBlcmF0dXJlcyksIGFuZCAzKSBzcGVjaWVzIGhhdmUgdW5pcXVlIHRoZXJtYWwgbGltaXRzIGFuZCBzcGVjaWVzLXNwZWNpZmljIGFjY2xpbWF0aW9uIChDVG1heCBwcmVkaWN0ZWQgdXNpbmcgd2hpY2hldmVyIGVudmlyb25tZW50YWwgZmFjdG9yIGFuZCBkdXJhdGlvbiBpcyB0aGUgc3Ryb25nZXN0IGNhbmRpZGF0ZSBmb3IgZHJpdmluZyBhY2NsaW1hdGlvbiAtIGZyb20gdGhlIGNvcnJlbGF0aW9uIGFuYWx5c2lzKS4gSW4gYWxsIGNhc2VzLCBkYXRhIGlzIGZpbHRlcmVkIHRvIGp1c3QgdGhlcm1hbCBsaW1pdHMgb2YgYWR1bHQgZmVtYWxlcy4gCgojIyMgU2NlbmFyaW8gMQpgYGB7cn0KbWVhbl9jdG1heCA9IGZ1bGxfZGF0YSAlPiUgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgc3VtbWFyaXplKCJtZWFuX2N0bWF4IiA9IG1lYW4oY3RtYXgpKSAlPiUgCiAgYXJyYW5nZShtZWFuX2N0bWF4KQoKa25pdHI6OmthYmxlKG1lYW5fY3RtYXgpCmBgYAoKYGBge3J9CiMgIyBDb25zdHJ1Y3RzIHRoZSBVUkwgZm9yIHRoZSBmdWxsIHRlbXBlcmF0dXJlIGRhdGEgc2V0OyBSVU4gVEhJUyBPTkNFCiMgaGluZF91cmwgPSBjb25zdHJ1Y3ROV0lTVVJMKHNpdGVOdW1iZXJzID0gc2l0ZU51bWJlciwgcGFyYW1ldGVyQ2QgPSBwYXJhbWV0ZXJDZCwgc2VydmljZSA9ICJ1diIpCiMgCiMgaGluZF90ZW1wX2RhdGEgPSBpbXBvcnRXYXRlck1MMShoaW5kX3VybCwgYXNEYXRlVGltZSA9IFQpICU+JQojICAgbXV0YXRlKCJkYXRlIiA9IGFzLkRhdGUoZGF0ZVRpbWUpKSAlPiUKIyAgIHNlbGVjdChkYXRlLCAidGVtcCIgPSBYXzAwMDEwXzAwMDAwKQojIAojIHdyaXRlLnRhYmxlKHggPSBoaW5kX3RlbXBfZGF0YSwgZmlsZSA9ICJoaW5kY2FzdF90ZW1wcy5jc3YiLCByb3cubmFtZXMgPSBGLCBzZXAgPSAiLCIpCmBgYAoKYGBge3J9CiMgZ2dwbG90KGhpbmRfdGVtcF9kYXRhLCBhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wKSkgKyAKIyAgIGdlb21fbGluZShsaW5ld2lkdGggPSAwLjEpICsgCiMgICBsYWJzKHggPSAiRGF0ZSIsIAojICAgICAgICB5ID0gIldhdGVyIFRlbXBlcmF0dXJlICjCsEMpIikgKwojICAgdGhlbWVfbWF0dCgpCmBgYAoKSW4gdGhlIHNpbXBsZXN0IHNjZW5hcmlvLCBzcGVjaWVzIHRoZXJtYWwgbGltaXRzIGFyZSBzdGF0aWMgdGhyb3VnaCB0aW1lLCByZXByZXNlbnRlZCBieSB0aGUgYXZlcmFnZSBDVG1heCBvZiBhZHVsdCBmZW1hbGUgY29wZXBvZHMuIEluIHRoaXMgc2NlbmFyaW8sIG9ubHkgdGhyZWUgb2YgdGhlIHNldmVuIG9ic2VydmVkIHNwZWNpZXMgYXJlIGV4cG9zZWQgdG8gdGhlcm1hbCBzdHJlc3MgKHRlbXBlcmF0dXJlcyB3aXRoaW4gNcKwQyBvZiBDVG1heCkuIFRlbXBlcmF0dXJlcyBhcHByb2FjaGVkIHRoZSB0aGVybWFsIGxpbWl0IG9mICpMZXB0b2RpYXB0b211cyBzaWNpbGlzKiBvbiBhIGhhbmRmdWwgb2YgZGF5cy4gQnkgY29udHJhc3QsICpTZW5lY2VsbGEgY2FsYW5vaWRlcyogYW5kICpMaW1ub2NhbGFudXMgbWFjcnVydXMqIHdlcmUgYm90aCBleHBvc2VkIHRvIHN1YnN0YW50aWFsIHRoZXJtYWwgc3RyZXNzIHRocm91Z2hvdXQgYSBsYXJnZSBwb3J0aW9uIG9mIHRoZSB5ZWFyLCBsaWtlbHkgZXhwbGFpbmluZyB3aHkgdGhlc2Ugc3BlY2llcyBhcmUgYWJzZW50IGZyb20gdGhlIGNvbW11bml0eSBmb3IgdGhlIHN1bW1lciBhbmQgZmFsbCBwZXJpb2RzLiAKCmBgYHtyIHN1cHAtZmlnLWhpbmQxX3NjZW5hcmlvLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KaGluZDFfZGF0YSA9IGhpbmRfdGVtcF9kYXRhICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXplKCJkYWlseV9tYXgiID0gbWF4KHRlbXApLAogICAgICAgICAgICAiZGFpbHlfbWVhbiIgPSBtZWFuKHRlbXApLCkgJT4lIAogIGJpbmRfY29scyhwaXZvdF93aWRlcihtZWFuX2N0bWF4LCBuYW1lc19mcm9tID0gc3BfbmFtZSwgdmFsdWVzX2Zyb20gPSBtZWFuX2N0bWF4KSkgJT4lICAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUsIC1kYWlseV9tYXgsIC1kYWlseV9tZWFuKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAic3BlY2llcyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibWVhbl9jdG1heCIpICU+JSAgCiAgbXV0YXRlKGxpbV9kaWZmID0gbWVhbl9jdG1heCAtIGRhaWx5X21heCkgJT4lICAKICBtdXRhdGUoZG95ID0geWRheShkYXRlKSwKICAgICAgICAgIm1ldGhvZCIgPSAiTm9fYWNjbGltYXRpb24iKQoKaGluZF9kYWlseV90ZW1wX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZSgicmFuZ2VfdGVtcCIgPSBtYXhfdGVtcCAtIG1pbl90ZW1wKQoKI3RhYmxlKGhpbmQxX2RhdGEkc3BlY2llcykKCmhpbmQxX2RhdGEgJT4lIAogIGZpbHRlcihsaW1fZGlmZiA8PSA1KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBzcGVjaWVzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKHNlID0gRikgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlIFxuKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCiMjIyBTY2VuYXJpbyAyCkluIHRoZSBzZWNvbmQgc2NlbmFyaW8sIHRoZXJtYWwgbGltaXRzIHZhcnkgd2l0aGluIGFuZCBiZXR3ZWVuIHNwZWNpZXMuIEEgc2ltcGxlIG1vZGVsIGlzIHVzZWQgdG8gcHJlZGljdCBzcGVjaWVzIHRoZXJtYWwgbGltaXRzIGJhc2VkIG9uIG1lYW4gZGFpbHkgdGVtcGVyYXR1cmUgKENUbWF4IGFzIGEgZnVuY3Rpb24gb2Ygc3BlY2llcyBhbmQgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZSwgYnV0IHdpdGhvdXQgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlc2UgdHdvIGZhY3RvcnMpLiBUaGVzZSBwcmVkaWN0ZWQgdGhlcm1hbCBsaW1pdHMgYXJlIHRoZW4gY29tcGFyZWQgYWdhaW5zdCB0aGUgbWF4aW11bSBkYWlseSB0ZW1wZXJhdHVyZSB0byBlc3RpbWF0ZSB0aGVybWFsIHN0cmVzcywgYXMgaW4gU2NlbmFyaW8gMS4gSW5jbHVkaW5nIHRoaXMgc2ltcGxlIGZvcm0gb2YgYWNjbGltYXRpb24gaW4gdGhlIG1vZGVsIHJlZHVjZWQgdGhlIGRlZ3JlZSBvZiB0aGVybWFsIHN0cmVzcyBmb3IgZWFjaCBzcGVjaWVzLCBlbGltaW5hdGluZyBpdCBlbnRpcmVseSBmb3IgKkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMqLiBOb3RlIHRoYXQgdGhlIG1hZ25pdHVkZSBvZiB0aGUgcHJlZGljdGVkIHN0cmVzcyBpcyAgbG93IGVub3VnaCB0aGF0IHJlbW92aW5nIHRoZSA1wrBDIGJ1ZmZlciBhcm91bmQgdGhlIHByZWRpY3RlZCB0aGVybWFsIGxpbWl0cyB3b3VsZCBhY3R1YWxseSBsaW1pdCBwcmVkaWN0ZWQgdGhlcm1hbCBzdHJlc3MgdG8ganVzdCBhIGZldyBkYXlzIGZvciAqU2VuZWNlbGxhIGNhbGFub2lkZXMqLiAKCmBgYHtyIHN1cHAtZmlnLWhpbmQyX3NjZW5hcmlvLCBmaWcuaGVpZ2h0PTUsIGZpZy53aWR0aD0xMH0KaGluZGNhc3RfbW9kZWwxID0gbG0oZGF0YSA9IGZpbHRlcihmdWxsX2RhdGEsIHNleCA9PSAiZmVtYWxlIiksCiAgICAgICAgICAgICAgICAgICAgIGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wICsgc3BfbmFtZSkKCmhpbmQyX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcml6ZSgiY29sbGVjdGlvbl90ZW1wIiA9IG1lYW4odGVtcCksCiAgICAgICAgICAgICJkYWlseV9tYXgiID0gbWF4KHRlbXApKSAlPiUgCiAgYmluZF9jb2xzKAogICAgcGl2b3Rfd2lkZXIobWVhbl9jdG1heCwgCiAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc3BfbmFtZSwgCiAgICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG1lYW5fY3RtYXgpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKC1kYXRlLCAtZGFpbHlfbWF4LCAtY29sbGVjdGlvbl90ZW1wKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAic3BfbmFtZSIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibWVhbl9jdG1heCIpICU+JSAKICBzZWxlY3QoLW1lYW5fY3RtYXgpICU+JSAKICBtdXRhdGUoInByZWRfY3RtYXgiID0gcHJlZGljdC5sbSAoaGluZGNhc3RfbW9kZWwxLCBuZXdkYXRhID0gLikpICU+JSAKICBzZWxlY3QoZGF0ZSwgImRhaWx5X21lYW4iID0gY29sbGVjdGlvbl90ZW1wLCBkYWlseV9tYXgsICJzcGVjaWVzIiA9IHNwX25hbWUsIHByZWRfY3RtYXgpICU+JSAKICBtdXRhdGUobGltX2RpZmYgPSBwcmVkX2N0bWF4IC0gZGFpbHlfbWF4KSAlPiUgCiAgI2ZpbHRlcihsaW1fZGlmZiA8PSAwKSAlPiUgIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpLAogICAgICAgICAibWV0aG9kIiA9ICJDb25zdGFudF9hY2NsaW1hdGlvbiIpCgojIGdncGxvdChoaW5kMl9kYXRhLCBhZXMoeCA9IGRhaWx5X21lYW4sIHkgPSBwcmVkX2N0bWF4LCBjb2xvdXIgPSBzcGVjaWVzKSkgKwojICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgCgojIHRhYmxlKGhpbmQyX2RhdGEkc3BlY2llcykKaGluZDJfZGF0YSAlPiUgIAogIGZpbHRlcihsaW1fZGlmZiA8PSA1KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBzcGVjaWVzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKCkgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlIFxuKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCiMjIyBTY2VuYXJpbyAzClRoZSBmaW5hbCBzY2VuYXJpbyBhbGxvd3MgdGhlIGVudmlyb25tZW50YWwgdmFyaWFibGUgdXNlZCB0byBwcmVkaWN0IENUbWF4IHRvIHZhcnkgYmV0d2VlbiBzcGVjaWVzLiBGb3Igc3BlY2llcyBvYnNlcnZlZCBpbiBmZXdlciB0aGFuIDUgY29sbGVjdGlvbnMsIHdlIHVzZSB0aGUgc2FtZSBhcHByb2FjaCBhcyBpbiBTY2VuYXJpbyAyLiBGb3Igc3BlY2llcyBvYnNlcnZlZCBpbiBtb3JlIHRoYW4gNSBjb2xsZWN0aW9ucywgaG93ZXZlciwgdGhlIGZhY3RvciB3aXRoIHRoZSBzdHJvbmdlc3QgY29ycmVsYXRpb24gd2l0aCBDVG1heCBpcyB1c2VkIHRvIHByZWRpY3QgdGhlcm1hbCBsaW1pdHMuIFRoZXNlIGZhY3RvcnMgYXJlIGluY2x1ZGVkIGJlbG93LgoKYGBge3J9CmhpbmRfcHJlZHMgPSBjb3JyX3ZhbHMgJT4lICAKICBmaWx0ZXIoc2lnID09ICJTaWcuIikgJT4lIAogIGRyb3BfbmEoY29ycmVsYXRpb24pICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUKICBhcnJhbmdlKGRlc2MoY29ycmVsYXRpb24pKSAlPiUgCiAgc2xpY2VfaGVhZChuID0gMSkgJT4lIAogIHNlbGVjdCgiU3BlY2llcyIgPSBzcF9uYW1lLCAiUHJlZGljdG9yIiA9IHBhcmFtZXRlciwgIkR1cmF0aW9uIiA9IGR1cmF0aW9uLCAiQ29ycmVsYXRpb24iID0gY29ycmVsYXRpb24sICJQLVZhbHVlIiA9IHAudmFsdWUpCgprbml0cjo6a2FibGUoaGluZF9wcmVkcywgYWxpZ24gPSAiYyIpCmBgYAoKYGBge3J9CmhpbmQzX2RhdGEgPSBoaW5kMl9kYXRhICU+JSAjIENvbnRhaW5zIGRhdGEgZm9yIHNwZWNpZXMgdGhhdCB3b24ndCBjaGFuZ2UgZnJvbSBzY2VuYXJpbyAyCiAgZmlsdGVyKCEoc3BlY2llcyAlaW4lIGNvcnJfdmFscyRzcF9uYW1lKSkKCnByZWRzX3RvX3B1bGwgPSBoaW5kX3ByZWRzICU+JSAgCiAgc2VsZWN0KFNwZWNpZXMsIFByZWRpY3RvciwgRHVyYXRpb24pIAoKZm9yKGkgaW4gMTpsZW5ndGgocHJlZHNfdG9fcHVsbCRTcGVjaWVzKSl7CiAgCiAgZHVyYXRpb24gPSBwcmVkc190b19wdWxsJER1cmF0aW9uW2ldCiAgCiAgaWYoZHVyYXRpb24gPT0gMCl7ICNUaGUgcHJpb3IgZGF5IHRlbXBlcmF0dXJlIG1ldHJpY3Mgc2hvdWxkIGJlIHVzZWQKICAgIAogICAgcHJlZGljdG9ycyA9IGhpbmRfZGFpbHlfdGVtcF9kYXRhICU+JSAKICAgICAgbXV0YXRlKGRhdGUgPSBkYXRlKSAKICAgIAogICAgcGFyYW1ldGVyID0gIm1lYW5fdGVtcCIgI3VzaW5nIG1lYW4gdGVtcGVyYXR1cmUgYXMgYSBwcm94eSBmb3IgY29sbGVjdGlvbiB0ZW1wCiAgICAKICAgIG1vZGVsX2RhdGEgPSBmdWxsX2RhdGEgJT4lCiAgICAgIGZpbHRlcihzcF9uYW1lICVpbiUgcHJlZHNfdG9fcHVsbCRTcGVjaWVzW2ldKSAlPiUgCiAgICAgIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICAgICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzX2RhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogICAgICBpbm5lcl9qb2luKHByZWRpY3RvcnMsIGpvaW5fYnkoY29sbGVjdGlvbl9kYXRlID09IGRhdGUpKSAlPiUgIAogICAgICBzZWxlY3QoY3RtYXgsIGNvbnRhaW5zKHBhcmFtZXRlcikpCiAgICAKICAgIGlmKGRpbShtb2RlbF9kYXRhKVsyXSA9PSAyKXsKICAgICAgaGluZC5tb2RlbCA9IGxtKGRhdGEgPSBtb2RlbF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgIGN0bWF4IH4gLikKICAgICAgCiAgICAgIHNwX2RhdGEgPSBwcmVkaWN0b3JzICU+JSAKICAgICAgICBzZWxlY3QoZGF0ZSwgY29udGFpbnMocGFyYW1ldGVyKSkgJT4lIAogICAgICAgIG11dGF0ZShwcmVkX2N0bWF4ID0gcHJlZGljdChoaW5kLm1vZGVsLCBuZXdkYXRhID0gLikpICU+JSAgCiAgICAgICAgc2VsZWN0KGRhdGUsIHByZWRfY3RtYXgpICU+JSAKICAgICAgICBpbm5lcl9qb2luKGhpbmRfZGFpbHlfdGVtcF9kYXRhLCBieSA9IGMoImRhdGUiKSkgJT4lIAogICAgICAgIG11dGF0ZSgic3BlY2llcyIgPSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0sCiAgICAgICAgICAgICAgICJkb3kiID0geWRheShkYXRlKSwKICAgICAgICAgICAgICAgbGltX2RpZmYgPSBwcmVkX2N0bWF4IC0gbWF4X3RlbXApICU+JSAKICAgICAgICBzZWxlY3QoZGF0ZSwgZGFpbHlfbWVhbiA9IG1lYW5fdGVtcCwgZGFpbHlfbWF4ID0gbWF4X3RlbXAsIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBkb3kpCiAgICAgIAogICAgICBoaW5kM19kYXRhID0gYmluZF9yb3dzKGhpbmQzX2RhdGEsIHNwX2RhdGEpCiAgICB9ZWxzZXsKICAgICAgcHJpbnQoYyh1bmlxdWUoc3BfZGF0YSRzcGVjaWVzKSwgIlRvbyBtYW55IGNvbHVtbnMgc2VsZWN0ZWQiKSkKICAgIH0KICAgIAogIH0KICAKICBpZihkdXJhdGlvbiA+IDApewogICAgI05laXRoZXIgdGhlIHByaW9yIGRheSBub3IgZGF5IG9mIG1ldHJpY3Mgc2hvdWxkIGJlIHVzZWQ7IHVzZSBkdXJhdGlvbiBhcyBuX2RheXMKICAgIAogICAgcHJlZGljdG9ycyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGhpbmRfZGFpbHlfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IGhpbmRfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSBkdXJhdGlvbikKICAgIAogICAgcGFyYW1ldGVyID0gcHJlZHNfdG9fcHVsbCRQcmVkaWN0b3JbaV0KICAgIAogICAgbW9kZWxfZGF0YSA9IGZ1bGxfZGF0YSAlPiUKICAgICAgZmlsdGVyKHNwX25hbWUgJWluJSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0pICU+JSAKICAgICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogICAgICBtdXRhdGUoY29sbGVjdGlvbl9kYXRlID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgICAgIGxlZnRfam9pbihwcmVkaWN0b3JzLCBqb2luX2J5KGNvbGxlY3Rpb25fZGF0ZSA9PSBkYXRlKSkgJT4lICAKICAgICAgc2VsZWN0KGN0bWF4LCBjb250YWlucyhwYXN0ZSgiZGF5XyIsIHBhcmFtZXRlciwgc2VwID0gIiIpKSkKICAgIAogICAgaWYoZGltKG1vZGVsX2RhdGEpWzJdID09IDIpewogICAgICBoaW5kLm1vZGVsID0gbG0oZGF0YSA9IG1vZGVsX2RhdGEsIAogICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiAuKQogICAgICAKICAgICAgc3BfZGF0YSA9IHByZWRpY3RvcnMgJT4lIAogICAgICAgIHNlbGVjdChkYXRlLCBjb250YWlucyhwYXJhbWV0ZXIpKSAlPiUgCiAgICAgICAgbXV0YXRlKHByZWRfY3RtYXggPSBwcmVkaWN0KGhpbmQubW9kZWwsIG5ld2RhdGEgPSAuKSkgJT4lICAKICAgICAgICBzZWxlY3QoZGF0ZSwgcHJlZF9jdG1heCkgJT4lIAogICAgICAgIGlubmVyX2pvaW4oaGluZF9kYWlseV90ZW1wX2RhdGEsIGJ5ID0gYygiZGF0ZSIpKSAlPiUgCiAgICAgICAgbXV0YXRlKCJzcGVjaWVzIiA9IHByZWRzX3RvX3B1bGwkU3BlY2llc1tpXSwKICAgICAgICAgICAgICAgImRveSIgPSB5ZGF5KGRhdGUpLAogICAgICAgICAgICAgICBsaW1fZGlmZiA9IHByZWRfY3RtYXggLSBtYXhfdGVtcCkgJT4lIAogICAgICAgIHNlbGVjdChkYXRlLCBkYWlseV9tZWFuID0gbWVhbl90ZW1wLCBkYWlseV9tYXggPSBtYXhfdGVtcCwgc3BlY2llcywgcHJlZF9jdG1heCwgbGltX2RpZmYsIGRveSkKICAgICAgCiAgICAgIGhpbmQzX2RhdGEgPSBiaW5kX3Jvd3MoaGluZDNfZGF0YSwgc3BfZGF0YSkKICAgICAgCiAgICB9ZWxzZXsKICAgICAgcHJpbnQoYyh1bmlxdWUoc3BfZGF0YSRzcGVjaWVzKSwgIlRvbyBtYW55IGNvbHVtbnMgc2VsZWN0ZWQiKSkKICAgIH0KICAgIAogIH0KfQoKCmhpbmQzX2RhdGEgPSBoaW5kM19kYXRhICU+JSAKICBtdXRhdGUoIm1ldGhvZCIgPSAiVmFyaWFibGVfYWNjbGltYXRpb24iKQpgYGAKClRoaXMgdGhpcmQgYXBwcm9hY2ggZGlkIG5vdCBhZmZlY3QgdGhlIHByZWRpY3RlZCBwYXR0ZXJucyBpbiAqTGltbm9jYWxhbnVzKiBvciAqU2VuZWNlbGxhKiAobmVpdGhlciBzcGVjaWVzIGhhcyBiZWVuIG9ic2VydmVkIGluIGVub3VnaCBjb2xsZWN0aW9ucyB0byBlc3RpbWF0ZSB0aGUgZWZmZWN0cyBvZiBkaWZmZXJlbnQgZW52aXJvbm1lbnRhbCBmYWN0b3JzKS4gQ2hhbmdpbmcgdGhlIGFjY2xpbWF0aW9uIGFwcHJvYWNoIGRpZCBhZmZlY3QgcGF0dGVybnMgaW4gdGhlcm1hbCBsaW1pdHMgaW4gdGhlIG90aGVyIHNwZWNpZXMgdGhvdWdoLiBUaGUgZmlndXJlIGJlbG93IHNob3dzIGhvdyBwcmVkaWN0ZWQgd2FybWluZyB0b2xlcmFuY2UgdmFyaWVzIG92ZXIgdGhlIHllYXIgaW4gdGhlIHNldmVuIHNwZWNpZXMsIGJhc2VkIG9uIHRoZSB0aHJlZSBkaWZmZXJlbnQgcHJlZGljdGlvbiBtZXRob2RzLiBJbiBnZW5lcmFsLCBjb25zdGFudCB0aGVybWFsIGxpbWl0cyAodGhlICdubyBhY2NsaW1hdGlvbicgbWV0aG9kKSByZXN1bHRlZCBpbiBsYXJnZXIgd2FybWluZyB0b2xlcmFuY2UgZHVyaW5nIHRoZSB3aW50ZXIgYW5kIGxvd2VyIHdhcm1pbmcgdG9sZXJhbmNlIGR1cmluZyB0aGUgc3VtbWVyLCBhbHRob3VnaCB0aGlzIGVmZmVjdCB3YXMgc21hbGwgaW4gbW9zdCBzcGVjaWVzLiAgICAgCmBgYHtyIHN1cHAtZmlnLWhpbmRfY2FzdF9zdW1tYXJ5LCBmaWcud2lkdGg9MTMsIGZpZy5oZWlnaHQ9MTB9CnN5bnRoZXNpcyA9IGJpbmRfcm93cygKICBzZWxlY3QoaGluZDFfZGF0YSwgZGF0ZSwgZG95LCBkYWlseV9tZWFuLCBkYWlseV9tYXgsIHNwZWNpZXMsICJwcmVkX2N0bWF4IiA9IG1lYW5fY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpLAogIHNlbGVjdChoaW5kMl9kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpLAogIHNlbGVjdChoaW5kM19kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBtZXRob2QpKSAlPiUgCiAgbXV0YXRlKG1ldGhvZCA9IGZjdF9yZWxldmVsKG1ldGhvZCwgIk5vX2FjY2xpbWF0aW9uIiwgIkNvbnN0YW50X2FjY2xpbWF0aW9uIiwgIlZhcmlhYmxlX2FjY2xpbWF0aW9uIikpICU+JSAKICBmaWx0ZXIoIShzcGVjaWVzID09ICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iICYgbWV0aG9kID09ICJWYXJpYWJsZV9hY2NsaW1hdGlvbiIpKQoKY2xpbWF0b2xvZ3kgPSBzeW50aGVzaXMgJT4lIAogIGdyb3VwX2J5KHNwZWNpZXMsIGRveSwgbWV0aG9kKSAlPiUgIAogIHN1bW1hcmlzZSgibWVhbl9kaWZmIiA9IG1lYW4obGltX2RpZmYpLAogICAgICAgICAgICAibWluX2RpZmYiID0gbWluKGxpbV9kaWZmKSwKICAgICAgICAgICAgIm1heF9kaWZmIiA9IG1heChsaW1fZGlmZikpICU+JSAKICBtdXRhdGUobWV0aG9kID0gZmN0X3JlbGV2ZWwobWV0aG9kLCAiTm9fYWNjbGltYXRpb24iLCAiQ29uc3RhbnRfYWNjbGltYXRpb24iLCAiVmFyaWFibGVfYWNjbGltYXRpb24iKSkKCmFjY19lZmZlY3RzID0gc3ludGhlc2lzICU+JSAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYyhkYXRlLCBzcGVjaWVzLCBkb3kpLCAKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gbWV0aG9kLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IGxpbV9kaWZmKSAlPiUgIAogIG11dGF0ZSgiY29uc3RfYWNjX2VmZmVjdCIgPSBDb25zdGFudF9hY2NsaW1hdGlvbiAtIE5vX2FjY2xpbWF0aW9uLAogICAgICAgICAidmFyX2FjY19lZmZlY3QiID0gVmFyaWFibGVfYWNjbGltYXRpb24gLSBOb19hY2NsaW1hdGlvbikKCmdncGxvdChzeW50aGVzaXMsIGFlcyh4ID0gZG95LCB5ID0gbGltX2RpZmYsIGNvbG91ciA9IG1ldGhvZCkpICsgCiAgZmFjZXRfd3JhcChzcGVjaWVzfi4pICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1LCBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMSkgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlICjCsEMgQWJvdmUgRGFpbHkgTWF4KSIpICsgCiAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE4KSArIAogIHRoZW1lKHN0cmlwLnRleHQueC50b3AgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKYGBgCgpgYGB7ciBzdXBwLWZpZy1hY2Nfc2NlbmFyaW9fZWZmZWN0cywgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9N30Kd3RfaGluZGNhc3Rfc3VtbWFyeSA9IHN5bnRoZXNpcyAlPiUgIAogIG11dGF0ZSgieWVhciIgPSB5ZWFyKGRhdGUpKSAlPiUgCiAgZ3JvdXBfYnkoc3BlY2llcywgeWVhciwgbWV0aG9kKSAlPiUgCiAgc3VtbWFyaXNlKCJtaW5fd3QiID0gbWluKGxpbV9kaWZmKSwKICAgICAgICAgICAgIm1heF93dCIgPSBtYXgobGltX2RpZmYpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKG1pbl93dCwgbWF4X3d0KSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm1ldHJpYyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAid3QiKSAlPiUgCiAgZ3JvdXBfYnkoc3BlY2llcywgbWV0aG9kLCBtZXRyaWMpICU+JSAKICBzdW1tYXJpc2UoIm1lYW5fd3QiID0gbWVhbih3dCkpCgp3dF9oaW5kY2FzdF9zdW1tYXJ5ICU+JSAKICBmaWx0ZXIobWV0cmljID09ICJtaW5fd3QiKSAlPiUgCmdncGxvdChhZXMoeCA9IG1ldGhvZCwgeSA9IG1lYW5fd3QsIGdyb3VwID0gc3BlY2llcywgY29sb3VyID0gc3BlY2llcykpICsgCiAgI2ZhY2V0X3dyYXAoLn5tZXRyaWMsIHNjYWxlcyA9ICJmcmVlX3kiKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIGxhYnMoeCA9ICJTY2VuYXJpbyIsIAogICAgICAgeSA9ICJNZWFuIFllYXJseSBNaW5pbXVtIFdUICjCsEMpIikgKyAKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAo=